2012-08-08 28 views
12

我想用套接字做一個HTTP request。我的代碼如下:C#:如何使用套接字執行HTTP請求?

using System; 
using System.Net; 
using System.Net.Sockets; 
using System.Text; 
class test 
{ 
    public static void Main(String[] args) 
    { 
     string hostName = "127.0.0.1"; 
     int hostPort = 9887; 
     int response = 0; 

     IPAddress host = IPAddress.Parse(hostName); 
     IPEndPoint hostep = new IPEndPoint(host, hostPort); 
     Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

     sock.Connect(hostep); 

     string request_url = "http://127.0.0.1/register?id=application/vnd-fullphat.test&title=My%20Test%20App"; 
     response = sock.Send(Encoding.UTF8.GetBytes(request_url)); 
     response = sock.Send(Encoding.UTF8.GetBytes("\r\n")); 

     bytes = sock.Receive(bytesReceived, bytesReceived.Length, 0); 
     page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes); 
     Console.WriteLine(page); 
     sock.Close(); 
    } 
} 

現在,當我執行上面的代碼沒有任何反應,而當我在瀏覽器中輸入我的request_url我從咆哮的通知說,Application Registered,我從瀏覽器中得到的響應是

SNP/2.0/0/OK/556 

我從我的代碼得到的回覆是SNP/3.0/107/BadPacket

那麼,我的代碼有什麼問題。

Snarl Request format specification

+1

是否有一個原因,你需要使用套接字而不是,比如'System.Net.Http.HttpClient'? – 2012-08-08 10:53:18

+2

或Webclient ... – steveg89 2012-08-08 10:56:50

+0

沒有沒有特定的原因。其實我並不知道「HttpCLient或Webclient」。但無論如何,我想了解什麼是我的上述代碼的青蛙。 – RanRag 2012-08-08 10:58:34

回答

7

您必須在年底內容長度和雙新線指示頭結束。

var request = "GET /register?id=application/vnd-fullphat.test&title=My%20Test%20App HTTP/1.1\r\n" + 
    "Host: 127.0.0.1\r\n" + 
    "Content-Length: 0\r\n" + 
    "\r\n"; 

HTTP 1.1規範可以在這裏找到:http://www.w3.org/Protocols/rfc2616/rfc2616.html

+0

謝謝隊友。正是我在找的東西。 – kurt 2016-04-09 22:10:35

1

您的要求是不正確的。據wikipedia, a HTTP Get request有看起來像:

string request = "GET /register?id=application/vnd-fullphat.test&title=My%20Test%20App HTTP/1.1\r\nHost: 127.0.0.1\r\n"; 
+0

我仍然在使用'SNP/3.0/107/BadPacket' – RanRag 2012-08-08 11:05:09

+3

這聽起來像你需要更多的東西,比如Connection,Accept或Accept-Encoding。 PVitt展示的是一個最小的請求,儘管這可能不足以滿足您的特定協議。按照上面的建議嘗試使用WebClient,看看是否可行,以確保API能夠正常工作。 – 2012-08-08 11:27:45

+0

根據接受的答案,它一定是'Content-Length'。 – vapcguy 2017-05-11 20:13:43

13

我一無所知SNP。你的代碼在接收部分有點混亂。我使用下面的示例發送和讀取HTTP GET請求的服務器響應。首先讓我們看看請求,然後檢查響應。

HTTP GET請求:

GET/HTTP/1.1 
Host: 127.0.0.1 
Connection: keep-alive 
Accept: text/html 
User-Agent: CSharpTests 

string - "GET/HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nAccept: text/html\r\nUser-Agent: CSharpTests\r\n\r\n" 

服務器的HTTP響應頭:

HTTP/1.1 200 OK 
Date: Sun, 07 Jul 2013 17:13:10 GMT 
Server: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16 
Last-Modified: Sat, 30 Mar 2013 11:28:59 GMT 
ETag: \"ca-4d922b19fd4c0\" 
Accept-Ranges: bytes 
Content-Length: 202 
Keep-Alive: timeout=5, max=100 
Connection: Keep-Alive 
Content-Type: text/html 

string - "HTTP/1.1 200 OK\r\nDate: Sun, 07 Jul 2013 17:13:10 GMT\r\nServer: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16\r\nLast-Modified: Sat, 30 Mar 2013 11:28:59 GMT\r\nETag: \"ca-4d922b19fd4c0\"\r\nAccept-Ranges: bytes\r\nContent-Length: 202\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n" 

我有意中省略了服務器響應的主體,因爲我們已經知道它到底是202個字節,如指定通過響應頭中的Content-Length。

查看HTTP規範將顯示HTTP頭以空行(「\ r \ n \ r \ n」)結尾。所以我們只需要搜索它。

讓我們看看一些實際的代碼。假定一個System.Net.Sockets.Socket類型的變量套接字。

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
socket.Connect("127.0.0.1", 80); 
string GETrequest = "GET/HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nAccept: text/html\r\nUser-Agent: CSharpTests\r\n\r\n"; 
socket.Send(Encoding.ASCII.GetBytes(GETrequest)); 

我們已經發送請求到服務器,讓我們接收並正確解析響應。

bool flag = true; // just so we know we are still reading 
string headerString = ""; // to store header information 
int contentLength = 0; // the body length 
byte[] bodyBuff = new byte[0]; // to later hold the body content 
while (flag) 
{ 
// read the header byte by byte, until \r\n\r\n 
byte[] buffer = new byte[1]; 
socket.Receive(buffer, 0, 1, 0); 
headerString += Encoding.ASCII.GetString(buffer); 
if (headerString.Contains("\r\n\r\n")) 
{ 
    // header is received, parsing content length 
    // I use regular expressions, but any other method you can think of is ok 
    Regex reg = new Regex("\\\r\nContent-Length: (.*?)\\\r\n"); 
    Match m = reg.Match(headerString); 
    contentLength = int.Parse(m.Groups[1].ToString()); 
    flag = false; 
    // read the body 
    bodyBuff = new byte[contentLength]; 
    socket.Receive(bodyBuff, 0, contentLength, 0); 
} 
} 
Console.WriteLine("Server Response :"); 
string body = Encoding.ASCII.GetString(bodyBuff); 
Console.WriteLine(body); 
socket.Close(); 

這可能是C#這樣做最壞的方法,有噸的類來處理HTTP請求和響應在.NET中,但仍,如果你需要它,它的工作原理。

0

HTTP請求的最低要求是 「GET/HTTP/1.0 \ r \ n \ r \ n」(如果刪除允許主機)。 但是在SNARL中,您必須輸入內容長度(我最常聽到的)。

所以,

 Socket sck = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); 

     sck.Connect(ip, port); 
     sck.Send(Encoding.UTF8.GetBytes("THE HTTP REQUEST HEADER")); 
     Console.WriteLine("SENT"); 
     string message = null; 
     byte[] bytesStored = new byte[ReceiveBufferSize]; 
     int k1 = sck.Receive(bytesStored); 
     for (int i = 0; i < k1; i++) 
     { 
      message = message + Convert.ToChar(bytesStored[i]).ToString(); 
     } 
     Console.WriteLine(message); // PRINT THE RESPONSE 

編輯:我對以前的窮人答案深感抱歉。它沒有形成,我添加了答案的主要思想/解決方案(沒有簡單的信息)。另外,我添加了源代碼。

我在幾個網站上測試過,效果很好。如果它不起作用,那麼你應該通過添加更多的頭部來解決它(最有可能的解決方案)。