我开始学习C(套接字)和Internet协议中的网络编程。
目前我专注于HTTP。
在使用C实现HTTP客户端的(非常)短暂体验期间,我发现有时您必须多次调用recv()才能从服务器获取整个消息 - 即使客户端没有发送在对recv()的单独调用之间向服务器发送消息。
例如:
当我尝试使用recv()调用实现HTTP客户端时,我只得到了标题(我想,我仍然是HTTP的新手)。 但是当我两次调用recv()时,我在第一次调用中得到了头文件,在第二次调用中得到了正文(html代码)。
这不是短缓冲区的问题,因为我使用的缓冲区足够长以容纳整个消息。
为什么会这样? 虽然没有客户端发送的新数据,但客户端必须多次调用recv()的原因是什么? 我认为如果客户端没有向服务器发送新数据,对recv()的调用将带来服务器的整个响应。
我认为这不是我的代码的问题,但是如果你要求代码,我可以在这里发布它没有问题。我认为这是不必要的,如果我错了,请纠正我。
我不认为这是相关的,但我正在使用Winsock2。
答案 0 :(得分:7)
TCP旨在面向流。接收方对发送的消息/数据包一无所知。它看到的只是一个简单的字节流。
所以你认为“我发了一条消息”,但是recv()只收到了一半。事实是,你从未发过邮件。您发送了一堆字节,并且您无法期望通过一次调用接收所有这些字节。您可以通过1,2或多个电话接收它们;您可以收到上一个“消息”的结尾以及下一个消息的开头,依此类推。
唯一的保证是您将按照它们发送的相同顺序接收字节,并且在流关闭之前您将永远不会收到0字节。这就是网络API的工作方式,你必须习惯它。
答案 1 :(得分:2)
接收方不知道发送呼叫的数量和每次呼叫的字节数
是在发件人。你不能说你想要一个10字节的recv
每个发送10个字节
一个recv呼叫可以接收三个发送的数据,
或者一个发送的数据可以分成三个接收...
如果它们有时匹配,则纯属巧合。
答案 2 :(得分:0)
你可以做的一件事是使用这样的循环。
while((recv(socketi,response,sizeof(response)-1,0))>0){
}
printf("\n%s",response);
在您发送的请求中,您必须明确说明您正在使用HTTP / 1.0 GET / HTTP/1.0
(在收到所有数据后关闭连接)。否则它会等到超时发生。
通过这样做,您将获得数组中的所有响应。无需多次调用recv()。