C中的HTTP:为什么我必须多次调用recv()?

时间:2014-01-25 17:12:53

标签: c sockets http web winsock2

我开始学习C(套接字)和Internet协议中的网络编程。

目前我专注于HTTP。

在使用C实现HTTP客户端的(非常)短暂体验期间,我发现有时您必须多次调用recv()才能从服务器获取整个消息 - 即使客户端没有发送在对recv()的单独调用之间向服务器发送消息。

例如:

当我尝试使用recv()调用实现HTTP客户端时,我只得到了标题(我想,我仍然是HTTP的新手)。 但是当我两次调用recv()时,我在第一次调用中得到了头文件,在第二次调用中得到了正文(html代码)。

这不是短缓冲区的问题,因为我使用的缓冲区足够长以容纳整个消息。

为什么会这样? 虽然没有客户端发送的新数据,但客户端必须多次调用recv()的原因是什么? 我认为如果客户端没有向服务器发送新数据,对recv()的调用将带来服务器的整个响应。

我认为这不是我的代码的问题,但是如果你要求代码,我可以在这里发布它没有问题。我认为这是不必要的,如果我错了,请纠正我。

我不认为这是相关的,但我正在使用Winsock2。

3 个答案:

答案 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()。