Case when blocking recv() returns less than requested bytes

后端 未结 3 1136
走了就别回头了
走了就别回头了 2020-12-08 23:27

The recv() library function man page mention that:

It returns the number of bytes received. It normally returns any data available, up to the reque

3条回答
  •  暖寄归人
    2020-12-09 00:16

    recv will return when there is data in the internal buffers to return. It will not wait until there is 100 bytes if you request 100 bytes.

    If you're sending 100 byte "messages", remember that TCP does not provide messages, it is just a stream. If you're dealing with application messages, you need to handle that at the application layer as TCP will not do it.

    There are many, many conditions where a send() call of 100 bytes might not be read fully on the other end with only one recv call when calling recv(..., 100); here's just a few examples:

    • The sending TCP stack decided to bundle together 15 write calls, and the MTU happened to be 1460, which - depending on timing of the arrived data might cause the clients first 14 calls to fetch 100 bytes and the 15. call to fetch 60 bytes - the last 40 bytes will come the next time you call recv() . (But if you call recv with a buffer of 100 , you might get the last 40 bytes of the prior application "message" and the first 60 bytes of the next message)

    • The sender buffers are full, maybe the reader is slow, or the network is congested. At some point, data might get through and while emptying the buffers the last chunk of data wasn't a multiple of 100.

    • The receiver buffers are full, while your app recv() that data, the last chunk it pulls up is just partial since the whole 100 bytes of that message didn't fit the buffers.

    Many of these scenarios are rather hard to test, especially on a lan where you might not have a lot of congestion or packet loss - things might differ as you ramp up and down the speed at which messages are sent/produced.

    Anyway. If you want to read 100 bytes from a socket, use something like

    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.
    
    }
    

提交回复
热议问题