阻塞recv()的情况返回少于请求的字节

recv()库函数手册页提到:

It returns the number of bytes received. It normally returns any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.

如果我们使用阻塞recv()调用并请求100个字节:

recv(sockDesc, buffer, size, 0); /* Where size is 100. */

并且只有50个字节由服务器发送,然后这个rec​​v()被阻塞,直到100个字节可用或它将返回接收50个字节.

情景可能是:

> sendign后,服务器崩溃只有50个字节
>糟糕的协议设计,其中服务器只发送50个字节,而客户端期望100个,服务器也在等待客户端的回复(即,套接字关闭连接尚未由recv将返回的服务器启动)

我对Linux / Solaris平台感兴趣.我没有开发环境来自己检查一下.

最佳答案
当内部缓冲区中有数据要返回时,recv将返回.如果您请求100个字节,它将不会等到有100个字节.

如果您要发送100字节“消​​息”,请记住TCP不提供消息,它只是一个流.如果您正在处理应用程序消息,则需要在应用程序层处理它,因为TCP不会这样做.

有许多条件,在调用recv(…,100)时,另一端可能无法完全读取100字节的send()调用,只有一个recv调用;这里只是几个例子:

>发送TCP堆栈决定捆绑15个写入调用,MTU恰好是1460,这取决于到达数据的时间可能导致客户端前14个调用获取100个字节,15个调用获取60个字节 – 下次调用recv()时,最后40个字节将会出现. (但是如果你用100的缓冲区调用recv,你可能得到先前应用程序“message”的最后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.

}

转载注明原文:阻塞recv()的情况返回少于请求的字节 - 代码日志