该recv()库函数手册页提及的是:
recv()
它返回接收的字节数。它通常返回任何可用数据,直到请求的数量,而不是等待收到请求的全部数量。
如果我们使用阻塞recv()调用并要求100字节:
recv(sockDesc, buffer, size, 0); /* Where size is 100. */
服务器仅发送50个字节,然后将recv()其阻止,直到100个字节可用为止,否则它将返回接收50个字节。
情况可能是:
sendign仅50个字节后服务器崩溃
错误的协议设计,其中服务器仅发送50个字节,而客户端期望100个字节,并且服务器还等待客户端的答复(即,套接字关闭连接尚未由recv将返回的服务器启动)
我对Linux / Solaris平台感兴趣。我没有开发环境可以自己检查。
当内部缓冲区中有数据要返回时,recv将返回。如果您请求100个字节,它不会等到100个字节为止。
如果要发送100字节的“消息”,请记住TCP不提供消息,它只是一个流。如果要处理应用程序消息,则需要在应用程序层进行处理,因为TCP不会这样做。
在许多情况下,调用recv(…,100)时,只有一个recv调用可能无法完全读取另一端的100字节send()调用;这里只是 几个 例子:
发送TCP堆栈决定将15个写调用捆绑在一起,而MTU恰好是1460,这取决于到达数据的时间,可能导致客户端的前14个调用获取100个字节,而15个调用获取60个字节-最后的40个字节将在您下次调用recv()时出现。(但是,如果使用缓冲区100调用recv,则可能会获得前一个应用程序“消息”的后40个字节,以及下一条消息的前60个字节)
发送者缓冲区已满,可能是读取器速度很慢,或者网络拥塞。在某些时候,数据可能会通过,在清空缓冲区时,最后一块数据不是100的倍数。
接收器缓冲区已满,而您的应用程序recv()数据时,它拉出的最后一个块只是部分,因为该消息的整个100字节都不适合缓冲区。
这些场景中的许多场景都很难测试,尤其是在您可能没有很多拥塞或数据包丢失的局域网上-随着您提高/降低消息发送/生成速度的速度,情况可能会有所不同。
无论如何。如果要从套接字读取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. }