C#:如何使用套接字执行 HTTP 请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11862890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C#: How to execute a HTTP request using sockets?
提问by RanRag
I am trying to make a HTTP requestusing sockets. My code is as follows:
我正在尝试HTTP request使用套接字。我的代码如下:
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();
}
}
Now when I execute the above code nothing happens whereas when I enter my request_urlin browser I get a notification from Snarl saying that Application Registeredand the response I get from browser is
现在,当我执行上面的代码时什么也没有发生,而当我request_url在浏览器中输入时,我收到了来自 Snarl 的通知,Application Registered我从浏览器得到的响应是
SNP/2.0/0/OK/556
The response I get from my code is SNP/3.0/107/BadPacket.
我从代码中得到的响应是SNP/3.0/107/BadPacket.
So, what is wrong with my code.
那么,我的代码有什么问题。
采纳答案by jgauffin
You must include content-length and double new line in the end to indicate end of header.
您必须在末尾包含 content-length 和双新行以指示标题的结尾。
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";
The HTTP 1.1 specification can be found here: http://www.w3.org/Protocols/rfc2616/rfc2616.html
HTTP 1.1 规范可以在这里找到:http: //www.w3.org/Protocols/rfc2616/rfc2616.html
回答by PVitt
Your request is not correct. According to wikipedia, a HTTP Get requesthas to look like:
您的要求不正确。根据维基百科,HTTP Get 请求必须如下所示:
string request = "GET /register?id=application/vnd-fullphat.test&title=My%20Test%20App HTTP/1.1\r\nHost: 127.0.0.1\r\n";
回答by Pedro
I know nothing about SNP. Your code is a bit confusing on the receive part. I have used the example bellow to send and read server response for an HTTP GET request. First let's take a look at the request and then examine the response.
我对 SNP 一无所知。您的代码在接收部分有点混乱。我使用下面的示例来发送和读取 HTTP GET 请求的服务器响应。首先让我们看一下请求,然后检查响应。
HTTP GET request :
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"
Server HTTP response header :
服务器 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"
I have purposely ommited the body of the server response, because we already know it is exactly 202 bytes, as specified by Content-Length in the response header.
我故意省略了服务器响应的主体,因为我们已经知道它正好是 202 个字节,正如响应头中的 Content-Length 所指定的那样。
A look over the HTTP specification will reveal that an HTTP header ends with an empty new line ("\r\n\r\n"). So we just need to search for it.
查看 HTTP 规范会发现 HTTP 标头以一个空的新行 ("\r\n\r\n") 结尾。所以我们只需要搜索它。
Let's see some code in action. Assume a variable socket of type System.Net.Sockets.Socket.
让我们看看一些运行中的代码。假设一个 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));
We have sent the request to the server, let's receive and correctly parse the response.
我们已经将请求发送到服务器,让我们接收并正确解析响应。
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();
This is probably the worst method to do this in C#, there are tons of classes to handle HTTP requests and responses in .NET, but still if you needed it, it works.
这可能是 C# 中最糟糕的方法,在 .NET 中有大量的类来处理 HTTP 请求和响应,但如果你需要它,它仍然可以工作。
回答by Adola
The minimum requirement for a HTTP request is "GET / HTTP/1.0\r\n\r\n" (if removing the Host is allowed). But in SNARL, you must input the content-length (what I most heard).
HTTP 请求的最低要求是“GET / HTTP/1.0\r\n\r\n”(如果允许删除主机)。但是在 SNARL 中,您必须输入内容长度(我最常听到的)。
So,
所以,
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[sck.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
I tested on several sites and it works perfectly. If it didn't work, then you should fix it by adding more header (most likely solution).
我在几个网站上测试过,效果很好。如果它不起作用,那么您应该通过添加更多标题来修复它(最有可能的解决方案)。

