Home > Enterprise >  Use of select with multiple sockets
Use of select with multiple sockets

Time:07-15

I would like to manage the sockets so that I can only accept connections once and then listen to the file descriptor of each socket and intercept the messages sent.

After a lot of trouble, I don't understand why my code systematically goes into the FD_ISSET() function while I put the file descriptor in my fd_set.

From what I've seen on other topics, it seems that you have to accept the connection systematically? Except that if I do that my code goes into an infinite wait.

int main(int argc, char **argv) {
    int socket = 0;
    // My client 1 socket
    int pOneSocket = 0;
    // My client 2 socket
    int pTwoSocket = 0;
    struct sockaddr_in serv_addr;
    int test = 0;
    // Create the server socket to listen
    createSocket(&socket,1337, &serv_addr);
    fd_set readfds;
    FD_ZERO(&readfds);
    //Enter the server socket to readfs
    FD_SET(socket, &readfds);
    while (1) {
        // Wait for changes on the server socket
        test = select(1024, &readfds, NULL, NULL, NULL);
        // If the socket fd is not on the readfs, then accept a new connecion
        if (FD_ISSET(test, &readfds) == 0)
            accept_connection(pOneSocket ? &pTwoSocket : &pOneSocket,
                      &socket, &serv_addr, &readfds);
        // Handle the connection and retreive command from file descriptor
        handleConnection(&test, &pOneSocket);
    }
    return 0;
}

On my handleConnection, I have all the code related to retreive commands:

void accept_connection(int *new_socket, int *socket, struct sockaddr_in *address, fd_set *readfds) {
    int addrlen = sizeof(*address);
    if((*new_socket = accept(*socket, (struct sockaddr *) address, (socklen_t *) &addrlen)) < 0) {
       fprintf(stderr, "\n Accept failed \n");
       exit(84);
    }
    FD_SET(*new_socket, readfds);
}

Currently, my code works to accept a connection, but gets stuck on the first command sent from the client.

CodePudding user response:

select() modifies the fd_set object(s) you pass to it, so each loop iteration needs to make a copy of them, not pass the original fd_sets you're using to track your connections. Something like this:

FD_SET(socket, &readfds);
while (1) {
    // Wait for changes on the sockets we want to read
    fd_set ready = readfds;
    test = select(1024, &ready, NULL, NULL, NULL);
    // If the socket fd is ready, then accept a new connecion
    if (FD_ISSET(socket, &ready))
       accept_connection(pOneSocket ? &pTwoSocket : &pOneSocket,
                      &socket, &serv_addr, &readfds);
    ... check the other fds that have previously been accepted to see if they're ready
  • Related