【发布时间】:2014-02-16 16:17:27
【问题描述】:
我已经开始学习 C(套接字)中的网络编程和 Internet 协议。
目前我专注于 HTTP。
在我使用 C 实现 HTTP 客户端的(非常)短暂的经验中,我发现有时您必须多次调用 recv() 才能从服务器获取整个消息 - 即使客户端没有发送在对 recv() 的单独调用之间向服务器发送消息。
例如:
当我尝试通过一次调用 recv() 来实现 HTTP 客户端时,我只得到了标头(我想,我仍然是 HTTP 的新手)。 但是当我两次调用 recv() 时,我在第一次调用中得到了标题,在第二次调用中得到了正文(html 代码)。
这不是缓冲区短的问题,因为我使用的缓冲区足够长,可以容纳整个消息。
为什么会这样? 尽管客户端没有发送新数据,但客户端必须多次调用 recv() 的原因是什么? 我以为如果客户端不向服务端发送新数据,调用recv()会带来服务端的全部响应。
我不认为这是我的代码的问题,但是如果您要索取代码,我可以在这里发布。我只是觉得这是不必要的,如果我错了,请纠正我。
我认为这无关紧要,但我正在使用 Winsock2。
【问题讨论】:
-
原始 I/O 函数通常必须总是在循环中调用,因为它们不保证任何成功。
-
但是第一次调用成功了——我在第一次调用中得到了标题。另外,什么是“原始函数”?谢谢。
-
但它“成功”了,但不能保证它读了多少。它最多可以读取一个字节并“成功”。所以你必须继续打电话,直到它说“没有更多数据,连接关闭”。 “原始”是指运营服务,如
read或recv或write。相比之下,像printf或fwrite这样的高级库函数只需要调用一次,因为它们承诺写入整个数据集(它们会在内部进行循环)。 -
感谢您对“原始”函数的解释。我怎么知道所有的数据都收到了?检查 recv() 返回 0 是否正常?
-
仔细阅读
recv()/send()的手册页,并了解至少对于套接字,这两个函数不一定接收/发送尽可能多的字节,但很少。因此,循环计算此类调用,直到所有数据或终止符已被接收/发送是一个好主意,而不是说必不可少的必要性。
标签: c sockets http web winsock2