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



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

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

并且服务器仅发送50个字节,然后此recv()被阻止,直到100个字节可用,否则它将返回接收50个字节。

情况可能是:

sendign仅50个字节后
  • 服务器崩溃
  • 错误的协议(protocol)设计,其中服务器仅发送50个字节,而客户端期望100个字节,并且服务器还等待客户端的答复(即,套接字关闭连接尚未由recv将返回的服务器启动)

    我对Linux/Solaris平台感兴趣。我没有开发环境可以自己检查。

    最佳答案

    当内部缓冲区中有数据要返回时,recv将返回。如果您请求100个字节,它不会等到100个字节为止。

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

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

  • 发送方TCP堆栈决定将15个写调用 bundle 在一起,而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.
    
    }
    

    07-24 09:46
    查看更多