代码之家  ›  专栏  ›  技术社区  ›  GrayWizardx

如何确定HTTP响应是否完成

  •  4
  • GrayWizardx  · 技术社区  · 15 年前

    我正在构建一个简单的代理,它将记录通过它传递的某些请求。代理不需要干扰正在通过它的流量(此时在项目中),因此我正在尝试在处理过程中尽可能少地分析原始请求/响应(请求和响应被推送到一个队列,以便在代理之外进行记录)。

    我的示例工作得很好,除了无法可靠地判断“响应”何时完成,所以我的连接保持打开的时间比需要的时间长。相关代码如下:

    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'ed等),我不想解码实际的响应来获取长度,并确定是否可以断开我的套接字。

    3 回复  |  直到 14 年前
        1
  •  2
  •   jgauffin    14 年前

    正如大卫指出的,关系应该保持开放一段时间。除非客户端这样做(或者如果keep-alive间隔过期),否则不应关闭连接。

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

    HTTP消息如下:

    REQUEST LINE
    HEADERS
    (empty line)
    BODY
    

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

    另一种选择是在 webserver 获取所有标题。只使用解析器,而不使用库中的任何内容,应该非常容易。

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

        2
  •  3
  •   David    15 年前

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

    除此之外,您确实需要在响应中解析Content-Length头以获得最佳值。

        3
  •  -1
  •   sukru    15 年前

    使用阻塞IO和多线程可能是您的答案。明确地

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

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

    推荐文章