如何判断HTTP响应是否完成

发布于 2024-09-11 15:14:12 字数 1293 浏览 4 评论 0原文

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

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

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

I am working on building a simple proxy which will log certain requests which are passed through it. The proxy does not need to interfere with the traffic being passed through it (at this point in the project) and so I am trying to do as little parsing of the raw request/response as possible durring the process (the request and response are pushed off to a queue to be logged outside of the proxy).

My sample works fine, except for a cannot reliably tell when the "response" is complete so I have connections left open for longer than needed. The relevant code is below:

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);

My question is whether there is an easy way to tell that the response is complete without parsing headers. Given that this response could be anything (encoded, encrypted, gzip'ed etc), I dont want to have to decode the actual response to get the length and determine if I can disconnect my socket.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淑女气质 2024-09-18 15:14:12

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

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

HTTP 消息如下所示:

REQUEST LINE
HEADERS
(empty line)
BODY

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

另一种选择是使用我的 webserver 中的解析器来获取所有标头。仅使用解析器应该很容易,而无需使用库中的任何内容。

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

As David pointed out, connections should remain open for a period of time. You should not close connections unless the client side does that (or if the keep alive interval expires).

Changing to HTTP/1.0 will not work since you are a server and it's the client that will specify HTTP/1.1 in the request. Sure, you can send a error message with HTTP/1.0 as version and hope that the client changes to 1.0, but it seems inefficient.

HTTP messages looks like this:

REQUEST LINE
HEADERS
(empty line)
BODY

The only way to know when a response is done is to search for the Content-Length header. Simply search for "Content-Length:" in the request buffer and extract everything to the linefeed. (But trim the found value before converting to int).

The other alternative is to use the parser in my webserver to get all headers. It should be quite easy to use just the parser and nothing more from the library.

Update: There is a better parser here: HttpParser.cs

左岸枫 2024-09-18 15:14:12

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

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

If you make a HTTP/1.0 request instead of 1.1, the server should close the connection as soon as it's through since it doesn't need to keep the connection open for another request.

Other than that, you really need to parse the content length header in the response to get the best value.

幽蝶幻影 2024-09-18 15:14:12

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

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

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

Using blocking IO and multiple threads might be your answer. Specifically

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

This is for textual data, however binary handling is similar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文