As others have mentioned, you can use select() to set a time limit for the socket to become readable.
By default, the socket will become readable when there's one or more bytes available in the socket receive buffer. I say "by default" because this amount is tunable by setting the socket receive buffer "low water mark" using the SO_RCVLOWAT socket option.
Below is a function you can use to determine if the socket is ready to be read within a specified time limit. It will return 1 if the socket has data available for reading. Otherwise, it will return 0 if it times out.
The code is based on an example from the book Unix Network Programming (www.unpbook.com) that can provide you with more information.
/* Wait for "timeout" seconds for the socket to become readable */
readable_timeout(int sock, int timeout)
{
struct timeval tv;
fd_set rset;
int isready;
FD_ZERO(&rset);
FD_SET(sock, &rset);
tv.tv_sec = timeout;
tv.tv_usec = 0;
again:
isready = select(sock+1, &rset, NULL, NULL, &tv);
if (isready < 0) {
if (errno == EINTR) goto again;
perror("select"); _exit(1);
}
return isready;
}
Use it like this:
if (readable_timeout(sock, 5/*timeout*/)) {
recv(sock, ...)
You mention handling SIGPIPE on the client side which is separate issue. If you are getting this is means your client is writing to the socket, even after having received a RST from the server. That is a separate issue from having a problem with a blocking call to recv().
The way that could arise is that the server crashes and reboots, losing its TCP state. Your client sends data to the server which sends back a RST, since it no longer has state for the connection. Your client ignores the RST and tries to send more data and it's this second send() which causes your program to receive the SIGPIPE signal.
What error were you getting from the call to recv()?