csocketsrecvposix-select

Does select() guarantee that all data is available for reading from a socket or only part of the data


I have a single-threaded multi-client program written in c.

If one client has a hideously slow network connection or is being malicious and limits their rate of send() tot he server application to something ridiculous like 1 byte/second, will select() return on the first byte received from the client (as the socket has become active) and then leave the read() call blocking while it waits for the additional 2000 bytes to be written, completely destroying the server and rendering it unreachable for the other clients; or will the select function only return when the malicious client has totally written all the bytes to some OS buffer, allowing the server to handle other clients in the meantime?


Solution

  • From the POSIX documentation about select:

    A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully.

    and

    A descriptor shall be considered ready for writing when a call to an output function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully.

    So all that is guaranteed is that a blocking socket will not block if you attempt to receive (for sockets in the read set) or send (for sockets in the write set).

    The amount of bytes that you will receive or is able to send is indeterminate.

    This is why receiving and sending often is done using loops and on non-blocking sockets.

    Also note that this "would not block" and "whether or not the function would transfer data successfully" could mean that the receive or send calls could return immediately with errors. Or in the case of receiving, return with the value 0 which means a connection-based connection is closed by the peer.