Sockets 确保HTTP消息的完整性

Sockets 确保HTTP消息的完整性,sockets,http,Sockets,Http,我目前正在开发一个应用程序,该应用程序应该能够获取网页并从其内容中提取信息 正如我从研究中了解到的(或者至少在我看来),没有理想的方法来确定HTTP消息的结尾 一般来说,我找到了两种不同的方法: 为套接字设置O_NONBLOCK标志,并在while循环中使用recv()获取数据。假设消息是完整的,如果消息流中没有字节,则消息将中断 依赖HTTP内容长度头并确定消息的结尾 这两种方法对我来说似乎都不完全安全。解决方案(1)可能在消息完成之前中断recv循环。另一方面,解决方案(2)要求正确设置内容

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

正如我从研究中了解到的(或者至少在我看来),没有理想的方法来确定HTTP消息的结尾

一般来说,我找到了两种不同的方法:

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

  • 依赖HTTP内容长度头并确定消息的结尾

  • 这两种方法对我来说似乎都不完全安全。解决方案(1)可能在消息完成之前中断recv循环。另一方面,解决方案(2)要求正确设置内容长度标题

    在这种情况下,最好的处理方法是什么?我能否始终依赖要设置的内容长度标题?

    让我从这里开始:

    我是否可以始终依赖要设置的内容长度标题

    不,你不能<代码>内容长度是可选的标题。但是,如果HTTP消息要符合RFC(cf),则必须提供一种确定其正文长度的方法。也就是说,只要没有指定内容长度,就准备好解析

    至于您最初的问题:确保消息的完整性实际上是TCP的工作。但由于存在诸如消息管道这样复杂的事情,因此最好在实践中检查两件事:

  • 是否已成功从网络缓冲区进行所有读取
  • 接收的字节数是否与预测的消息长度相同

  • 噢,正如@MartinJames所指出的,非阻塞可能不是最好的主意。

    HTTP响应的结尾定义如下:

  • 在使用传输编码分块的情况下,由最后一个(空)分块生成
  • 如果给定了内容长度头且未使用分块传输编码,则通过达到给定的长度
  • 在TCP连接结束时,如果未使用分块传输编码,则不会给出内容长度

  • 在前两种情况下,您有一个定义良好的端点,因此可以验证数据是否已完全接收。只有在最后一种情况下(TCP连接结束),在发送所有数据之前,您不知道连接是否已关闭。但通常情况下,您会遇到案例1或案例2。

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

    Connection: close
    
    当发出HTTP请求时,web服务器将在向您提供请求的完整页面后关闭连接,您将不必处理块


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

    使用协议,Luke'“O_NONBLOCK”对你的要求毫无用处,我甚至不知道你为什么建议它。无论如何,您必须在while循环中使用recv()获取数据。我在internet()上的研究中发现了非阻塞套接字。我遇到的问题是,如果没有更多的数据可获取,recv将阻塞,因此我应该知道在调用之前会发生这种情况。我找到的解决方案是假设当recv再次生成E_WOULDBLOCK或E_(在非阻塞模式下)时,消息是完整的。然后循环中断,应用程序可以继续。事实上,我没有试过这个。不过,我现在知道有一种安全且符合RFC的方法来解决我的问题。非常感谢您,也感谢您参考RFC。我想我现在开悟了,很荣幸。哦,欢迎来到stackoverflow:)谢谢,我很高兴谢谢你简洁的回答!啊,这是一个有趣的选择!非常感谢。