Listen to multiple ports from one server

c, linux, sockets

Solution

For each port that you want to listen to, you:

- Create a separate socket with `socket`.

- Bind it to the appropriate port with `bind`.

- Call `listen` on the socket so that it's set up with a listen queue.

At that point, your program is listening on multiple sockets. In order to accept connections on those sockets, you need to know which socket a client is connecting to. That's where `select` comes in. As it happens, I have code that does exactly this sitting around, so here's a complete tested example of waiting for connections on multiple sockets and returning the file descriptor of a connection. The remote address is returned in additional parameters (the buffer must be provided by the caller, just like accept).

(`socket_type` here is a typedef for `int` on Linux systems, and `INVALID_SOCKET` is `-1`. Those are there because this code has been ported to Windows as well.)

socket_type
network_accept_any(socket_type fds[], unsigned int count,
                   struct sockaddr *addr, socklen_t *addrlen)
{
    fd_set readfds;
    socket_type maxfd, fd;
    unsigned int i;
    int status;

    FD_ZERO(&readfds);
    maxfd = -1;
    for (i = 0; i < count; i++) {
        FD_SET(fds[i], &readfds);
        if (fds[i] > maxfd)
            maxfd = fds[i];
    }
    status = select(maxfd + 1, &readfds, NULL, NULL, NULL);
    if (status < 0)
        return INVALID_SOCKET;
    fd = INVALID_SOCKET;
    for (i = 0; i < count; i++)
        if (FD_ISSET(fds[i], &readfds)) {
            fd = fds[i];
            break;
        }
    if (fd == INVALID_SOCKET)
        return INVALID_SOCKET;
    else
        return accept(fd, addr, addrlen);
}

This code doesn't tell the caller which port the client connected to, but you could easily add an `int *` parameter that would get the file descriptor that saw the incoming connection.

Problem

Is it possible to bind and listen to multiple ports in Linux in one application?

Original source