4

我正在构建一个简单的代理,它将记录通过它传递的某些请求。代理不需要干扰通过它的流量(在项目的这一点),所以我试图在这个过程中尽可能少地解析原始请求/响应(请求和响应被推送关闭到要在代理之外记录的队列)。

我的示例工作正常,除了无法可靠地判断“响应”何时完成,因此我的连接打开时间超过了需要。相关代码如下:

var request = getRequest(url);
byte[] buffer;
int bytesRead = 1;
var dataSent = false;
var timeoutTicks = DateTime.Now.AddMinutes(1).Ticks;

Console.WriteLine("   Sending data to address: {0}", url);
Console.WriteLine("   Waiting for response from host...");
using (var outboundStream = request.GetStream()) {
   while (request.Connected && (DateTime.Now.Ticks < timeoutTicks)) {
      while (outboundStream.DataAvailable) {
         dataSent = true;
         buffer = new byte[OUTPUT_BUFFER_SIZE];
         bytesRead = outboundStream.Read(buffer, 0, OUTPUT_BUFFER_SIZE);

         if (bytesRead > 0) { _clientSocket.Send(buffer, bytesRead, SocketFlags.None); }

         Console.WriteLine("   pushed {0} bytes to requesting host...", _backBuffer.Length);
      }

      if (request.Connected) { Thread.Sleep(0); }
   }
}

Console.WriteLine("   Finished with response from host...");
Console.WriteLine("   Disconnecting socket");
_clientSocket.Shutdown(SocketShutdown.Both);

我的问题是是否有一种简单的方法可以在不解析标头的情况下判断响应是否完整。鉴于此响应可以是任何东西(编码、加密、gzip 等),我不想解码实际响应来获取长度并确定是否可以断开我的套接字。

4

3 回答 3

3

如果您发出 HTTP/1.0 请求而不是 1.1,则服务器应在连接完成后立即关闭连接,因为它不需要为另一个请求保持连接打开。

除此之外,您确实需要解析响应中的内容长度标头以获得最佳值。

于 2010-07-26T17:56:20.660 回答
3

正如大卫指出的那样,连接应该在一段时间内保持打开状态。除非客户端这样做(或者如果保持活动间隔到期),否则不应关闭连接。

更改为 HTTP/1.0 将不起作用,因为您是服务器,而客户端将在请求中指定 HTTP/1.1。当然,您可以发送带有 HTTP/1.0 作为版本的错误消息,并希望客户端更改为 1.0,但这似乎效率低下。

HTTP 消息如下所示:

REQUEST LINE
HEADERS
(empty line)
BODY

知道响应何时完成的唯一方法是搜索 Content-Length 标头。只需在请求缓冲区中搜索“Content-Length:”并将所有内容提取到换行符。(但在转换为 int 之前修剪找到的值)。

另一种选择是使用我的网络服务器中的解析器来获取所有标头。只使用解析器应该很容易,而不是库中的其他内容。

更新:这里有一个更好的解析器:HttpParser.cs

于 2010-07-26T18:20:37.327 回答
-1

使用阻塞 IO 和多线程可能是您的答案。具体来说

using(var response = request.GetResponse())
using(var stream = response.GetResponseStream())
using(var reader = new StreamReader(stream)
  data = reader.ReadToEnd()

这适用于文本数据,但二进制处理类似。

于 2010-07-26T17:55:53.730 回答