确保HTTP消息的完整性

时间:2016-03-02 16:14:51

标签: sockets http

我目前正在开发一个应用程序,它应该获取一个网页并从其内容中提取信息。

正如我从研究中学到的(至少在我看来),没有理想的方法来确定HTTP消息的结束。

一般来说,我发现了两种不同的方法:

  1. 为套接字设置O_NONBLOCK标志,并在while循环中使用recv()获取数据。如果流中没有字节,则假设消息已完成并中断。

  2. 依靠HTTP Content-Length标头并用它确定消息的结尾。

  3. 这两种方式对我来说似乎并不完全安全。解决方案(1)可能会在消息完成之前中断recv循环。另一方面,解决方案(2)需要正确设置Content-Length标头。

    在这种情况下,最好的方法是什么?我是否可以始终依赖Content-Length标头设置?

3 个答案:

答案 0 :(得分:0)

让我从这里开始:

  

我是否可以始终依赖Content-Length标头设置?

不,你不能。 Content-Length是一个可选标头。但是,如果HTTP消息要符合RFC标准,则绝对必须才能确定其长度(cf RFC7230, sec. 3.3.3)。话虽如此,只要未指定内容长度,就可以在chunked encoding上解析。

至于你原来的问题:确保消息的完整性实际上应该是TCP的工作。但是由于存在诸如消息流水线这样复杂的事情,最好在实践中检查两件事:

  1. 是否已从网络缓冲区读取所有内容?
  2. 接收的字节数是否与预测的消息长度相同?
  3. 哦,正如@MartinJames所说,非阻塞可能不是最好的主意。

答案 1 :(得分:0)

定义了HTTP响应的结束:

  1. 使用Transfer-Encoding chunked时的最终(空)块。
  2. 如果给出Content-length标头并且没有使用分块传输编码,则达到给定长度。
  3. 如果未使用分块传输编码,则在TCP连接结束时,不会给出Content-length。
  4. 在前两种情况下,您有一个定义明确的结束,因此您可以验证数据是否已完全接收。仅在最后一种情况下(TCP连接结束),您不知道在发送所有数据之前连接是否已关闭。但通常你会得到案例1或案例2。

答案 2 :(得分:0)

为了让您的生活更轻松,您可能想提供

Connection: close
在发出HTTP请求时

标题 - 在给出完整页面请求之后,Web服务器将关闭连接,您将不必处理块。

如果您只对这个页面感兴趣,并且不会请求额外的资源(脚本文件,图像等),那么这只是一个可行的选择 - 在后一种情况下,对于您的应用程序和应用程序而言,这将是一个非常低效的解决方案服务器