recv()
库函数手册页提到:
返回接收的字节数。它通常返回任何可用的数据,直到请求的数量,而不是等待收到所请求的全部金额。
如果我们使用阻止recv()
调用并请求100个字节:
recv(sockDesc, buffer, size, 0); /* Where size is 100. */
并且服务器只发送50个字节,然后阻止此recv()
,直到100个字节可用或者它将返回接收50个字节。
情景可能是:
服务器在sendign仅50字节后崩溃
糟糕的协议设计,其中服务器只发送50个字节,而客户端期望100个,服务器也在等待客户端的回复(即,套接字关闭连接尚未由recv将返回的服务器启动)
我对Linux / Solaris平台感兴趣。我没有自己查看的开发环境。
答案 0 :(得分:16)
recv将返回。如果你请求100个字节,它将不会等到有100个字节。
如果您要发送100字节“消息”,请记住TCP不提供消息,它只是一个流。如果您正在处理应用程序消息,则需要在应用程序层处理它,因为TCP不会这样做。
有很多很多条件,在调用recv时,只有一次recv调用,另一端可能无法完全读取100字节的send()调用(...,100);这里只是几个示例:
发送TCP堆栈决定捆绑15个写入调用,MTU恰好是1460,这取决于到达数据的时间可能导致客户端前14个调用获取100个字节和15个。调用获取60个字节 - 下次调用recv()时将返回最后40个字节。 (但是如果你用100的缓冲区调用recv,你可能会得到先前应用程序“message”的最后40个字节和下一个消息的前60个字节)
发件人缓冲区已满,读者可能很慢,或网络拥挤。在某些时候,数据可能会通过,而在清空缓冲区时,最后一块数据不是100的倍数。
接收器缓冲区已满,而你的应用程序recv()表示数据,它上拉的最后一个块只是部分,因为该消息的整个100字节不适合缓冲区。
< / LI>其中许多场景都很难测试,尤其是在可能没有大量拥塞或数据包丢失的局域网上 - 随着您发送/生成消息的速度上升和下降,情况可能会有所不同。 / p>
反正。如果要从套接字读取100个字节,请使用类似
的内容int
readn(int f, void *av, int n)
{
char *a;
int m, t;
a = av;
t = 0;
while(t < n){
m = read(f, a+t, n-t);
if(m <= 0){
if(t == 0)
return m;
break;
}
t += m;
}
return t;
}
...
if(readn(mysocket,buffer,BUFFER_SZ) != BUFFER_SZ) {
//something really bad is going on.
}
答案 1 :(得分:7)
行为由两件事决定。 recv低水位标记以及是否通过MSG_WAITALL
标志。如果传递此标志,则呼叫将阻塞,直到收到请求的字节数,即使服务器崩溃也是如此。另外,只要套接字的接收缓冲区中至少有SO_RCVLOWAT
字节可用,它就会返回。
<强> SO_RCVLOWAT 强>
设置最小字节数 套接字输入操作的过程。 SO_RCVLOWAT的默认值是 1.如果SO_RCVLOWAT设置为较大的值,则正常阻止接收呼叫 等到他们收到了 较低的水印值或 要求的金额。 (他们可能会回来 如果是低于水位的话 发生错误,捕获信号,或 接收中的下一个数据类型 队列与返回的队列不同, 例如带外数据)。这个选项 取一个int值。请注意,并非所有 实现允许此选项 设定。
答案 2 :(得分:2)
如果您准确阅读报价,最常见的情况是: