In TCP socket programming, if recv()
returns 0, it is taken as an indication that the other side closed its connection. However, AFAIK, the TCP RFC does not mandate the payload of TCP to be > 0. So, theoretically, a TCP stack can receive a message with payload 0.
So, essentially my question is what will recv()
returns if it receives a packet of payload sized 0? If it returns 0, then how do we distinguish it from a closed connection indication.
RETURN VALUE Upon successful completion, recv() shall return the length of the message in bytes. If no messages are available to be received and the peer has performed an orderly shutdown, recv() shall return 0. Otherwise, -1 shall be returned and errno set to indicate the error.
If successful, recv() returns the length of the message or datagram in bytes. The value 0 indicates the connection is closed. If unsuccessful, recv() returns -1 and sets errno to one of the following values: Error Code.
recv(IPC, Buffer, int n) is a blocking call, that is, if data is available it writes it to the buffer and immediately returns true, and if no data is available it waits for at least n seconds to receive any data.
So the answer to your question is that only one listen socket is needed, but new sockets will be created as clients connect (and removed as they disconnect).
TCP segments with a payload size of 0 are ubiquitous - they occur in pretty much every real-world TCP stream. They're sent whenever one side wishes to acknowledge reciept of data from the other, but has no data to send of its own. (These are commonly known as "ACK packets", but an "ACK packet" is just a regular segment that happens to contain no data).
Since such packets do not contain any data to deliver to the user application, they will not cause recv()
to return - recv()
will continue blocking until some actual data arrives. If recv()
returns 0, then it is a definite indication that the other end has closed its side of the connection and won't be sending any more data.
Remember that TCP is stream-oriented: there is not a 1-to-1 mapping between the data returned by a single recv()
call and the data in a single TCP segment. A single recv()
call might return a block of data that overlaps several TCP segments, and the data in a single TCP segment might be returned in multiple recv()
calls. The boundaries between TCP segments are not visible to the application using the BSD sockets API. If you want such boundaries, you need to either implement yourself using an application-layer protocol within the TCP stream, or use a datagram-oriented protocol like UDP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With