How can I skip reading from a connected client in C?

I am working on a TCP client server application with threads where clients take turns messaging the server(similar to a turn based game). The server sends a message to the client but the client has n seconds to respond. If the client doesn't respond in time the server should go to the next client without closing the connection. Is there a way to skip the read() call from the server?


It's not exactly clear what you mean about the server skipping read() calls, but I think you're talking about implementing the response timeout you describe. A common way to do that would be to engage the select() function, which allows you to wait for up to a specified amount of time for a file descriptor to become ready. You would then choose whether to read() or to move on to the next client based on whether select() signals that the wanted file descriptor is ready.

Very roughly, that might be something along these lines:

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>

// ...

    fd_set read_fds;

    FD_ZERO(&read_fds);
    FD_SET(client_fd, &read_fds);

    struct timeval timeout = { .tv_sec = 5, .tv_usec = 0 };

    int num_ready = select(client_fd + 1, &read_fds, NULL, NULL, &timeout);

    if (num_ready == -1) {
        // handle error ...
    } else if (num_ready == 0) {
        // handle timeout ...
    } else if (num_ready == 1) {
        // handle client response ...
    } else {
        // should not happen
        assert(0);
    }

You could also consider alternatives to select() with similar behavior, such as poll() and epoll_wait(). Also, you will probably find it advantageous in connection with this to configure the client sockets for non-blocking I/O, though this is not a technical requirement for use of the select(), etc. functions.

Do note that it's more complicated than that, however. There are at least these additional considerations:

  • You will need to be prepared for cases where the client disconnects.

  • if a client's response arrives too late then you will need to read that response and (presumably) discard it before you can handle any subsequent response from the same client.

  • Responses might be split into multiple pieces on the wire, so the beginning of a response might arrive within the timeout, yet the end not, and maybe not at all.

  • For robustness, you'll need to handle cases where the wait is interrupted by a signal prior to time expiring. Presumably you would want in that case to resume waiting, but not restart the timeout.