这是我的暂存代码:
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SocketsDemo
{
class Program
{
static void Main(string[] args)
{
Uri uri;
if (args.Any()) uri = new Uri(args[0]);
else uri = new Uri("http://odetocode.com/Articles/473.aspx"); //http://www.odetocode.com
var result = GetResource(uri);
Console.WriteLine(result);
Console.ReadLine();
}
private static string GetResource(Uri uri)
{
var host = uri.Host;
var resource = uri.PathAndQuery;
var hostEntry = Dns.GetHostEntry(host);
var socket = CreateSocket(hostEntry);
SendRequest(socket, host, resource);
return GetResponse(socket);
}
private static Socket CreateSocket(IPHostEntry hostEntry)
{
const int HTTP_PORT = 80;
var endPoint = new IPEndPoint(hostEntry.AddressList[0], HTTP_PORT);
var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(endPoint);
return socket.Connected ? socket : null;
}
private static void SendRequest(Socket socket, string host, string resource)
{
var requestMessage = String.Format(
"GET {0} HTTP/1.1\r\n" +
"HOST: {1}\r\n" +
"\r\n", resource, host);
var requestBytes = Encoding.ASCII.GetBytes(requestMessage);
socket.Send(requestBytes);
}
private static string GetResponse(Socket socket)
{
int bytesCount = 0;
var buffer = new byte[256];
var result = new StringBuilder();
do
{
bytesCount = socket.Receive(buffer);
result.Append(Encoding.ASCII.GetString(buffer, 0, bytesCount));
} while (bytesCount > 0);
return result.ToString();
}
}
}
当我将SendRequest
方法中的HTTP部分请求消息更改为HTTP / 1.0时 - 一切正常。
但是当我尝试在HTTP / 1.1上重复此操作时,此块do { .. } while (bytesCount > 0)
在181周期内挂起。看起来服务器或客户端无法处理最后一块字节。
任何人都可以解释这背后的原因以及如何通过对现有代码进行最小的更改来修复此问题。
答案 0 :(得分:2)
这是http的保持活力“功能”。发送消息后服务器不会断开连接,让您等待更多数据。
您必须解析HTTP标头。如果有一个Transfer-Encoding: chunked
,你必须解析你收到的块,直到你收到一个0字节的块。
如果它不是作为块发送的,则必须解析Content-Length
标头以查看总读取的字节数。
HTTP / 1.0不支持块,而某些客户端不支持保持连接活动,因此对于HTTP / 1.0,默认服务器行为应该是keep-alive off
,而对于HTTP / 1.1默认为on
。