我正在练习套接字编程,尝试发送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为止)或者遇到错误。
但是,我很少看到有人这样做,大多数人都建议使用长度指示器,即here和here。怀疑我是否因为上述方法而遗漏了任何内容。
方法2 :长度指标方法
好的,关于最优选的长度指示器方法,如何获得整个recv消息的总长度?
给出如下例子
这是我检索到的HTTP标头,有一个名为Content-Length
的字段。它是整个消息的长度(标题的大小+正文= 468)?
答案 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 0x0A
,1xx
或204
,或者响应是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.4和Section 8)以及RFC 7230(Section 3.3.3和Section 6)中。