如何确定我是否从recv()调用收到了整个消息

时间:2018-04-13 16:44:01

标签: sockets tcp http-headers

我正在练习套接字编程,尝试发送http请求,然后从服务器接收一些SOCK_STREAM数据。这个问题是关于接收过程的。

方法1 :我当前的方法只是使用while循环

while((received = recv(sockfd, response, BUFSIZ, 0)) > 0) {
        //process response
}

if(received < 0) {
        perror("Error receiving data!\n");
}

基本上,调用recv()直到它完成/关闭(返回0为止)或者遇到错误。

但是,我很少看到有人这样做,大多数人都建议使用长度指示器,即herehere。怀疑我是否因为上述方法而遗漏了任何内容。

方法2 :长度指标方法

好的,关于最优选的长度指示器方法,如何获得整个recv消息的总长度?

给出如下例子

enter image description here

这是我检索到的HTTP标头,有一个名为Content-Length的字段。它是整个消息的长度(标题的大小+正文= 468)?

1 个答案:

答案 0 :(得分:1)

在循环中调用var token = myNode.ToJToken().StripXmlPrefixCharacters(); var jsonText = token.ToString(Newtonsoft.Json.Formatting.Indented); // Or use Formatting.None if you don't want indenting 直到报告断开/错误只有在服务器在发送响应后关闭连接时才会正常工作(通常是因为客户端没有请求保持活动,或者服务器决定不遵守keep-alive),服务器在响应(或协议规定)中指示套接字闭包是消息数据的EOF。

在HTTP 0.9中,根本没有响应行或响应头。请求的文件本身按原样发送,EOF由套接字关闭指示。

在HTTP 1.0及更高版本中,recv()标头(如果存在的话)不是完整HTTP消息的总大小,而只是消息正文的总大小。消息头是可变长度的,以Content-Length字节序列终止。

读取HTTP响应的CORRECT方法是执行以下操作:

如果请求使用HTTP 0.9:

  • 从套接字读取,直到连接关闭/出错。

  • 然后关闭套接字。

这由original W3C specification of HTTP涵盖。

否则,如果响应使用HTTP 1.0或更高版本:

  • 从套接字读取,直到遇到表示响应行末尾的0x0D 0x0A 0x0D 0x0A字节序列,其中包含HTTP版本,状态代码和原因文本。

  • 然后从套接字读取,直到遇到表示响应头结束的0x0D 0x0A字节序列。

  • 然后分析响应行和标题以了解是否存在消息正文,如果存在,则以何种格式发送消息正文,这决定了您必须如何阅读它。

  • 阅读邮件正文,如果存在:

    • 如果响应状态代码为0x0D 0x0A 0x0D 0x0A1xx204,或者响应是304请求,则不会显示任何消息正文

    • 否则,如果存在HEAD标头并且其值不是Transfer-Encoding,请在chunks中读取消息正文,直到读取0长度的块。 / p>

    • 否则,如果存在identity标头,则从套接字读取,直到读取了指定的确切字节数,不多也不少。

    • 否则,如果Content-Length标头指示Content-Type媒体类型,请从套接字读取并解析MIME数据,直到到达最终终止MIME multipart/...

    • 否则,从套接字读取,直到连接关闭。

  • 如果没有成功读取响应,或者未使用keep-alive,则在HTTP 1.1响应或boundary标头中存在Connection: close标头在HTTP 1.0响应中不存在,然后关闭套接字。

这包含在RFC 2616(Section 4.4Section 8)以及RFC 7230(Section 3.3.3Section 6)中。