Question: 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?

Answer: 
From [the POSIX documentation about `select`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html):

> 
> 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.
How would the OS know that it has to wait for 2000 bytes to arrive? TCP is a stream, so the OS can't know after 1999 bytes that there's still a byte pending.

For UDP, the OS knows it's packet-based, and it will have the entire packet available once the last byte arrives. It can't deliver the first byte earlier, because the UDP checksum must be verified ovr the whole packet.