user1494517
user1494517

Reputation: 351

Detecting a timed out socket from a set of sockets

I'm currently building a server using winsock . My server will deal with multiple clients, so I am using select() function and the read, write and exception sets. I already know that if a particular socket times out, select() returns 0 .

But how could I identify the actual socket that timed out?

BTW, could anyone tell me what needs to happen to Some_Socket for the FD_ISSET(Some_Socket, &Exception) to return true?

Maybe I could use the above function to check every socket in the set?

EDIT:

Let's say I have this example:

int main(void){

       fd_set rfds;
       struct timeval tv;
       int retval;

       /* Watch stdin (fd 0) to see when it has input. */
       FD_ZERO(&rfds);

       for(int i = 0; i<clientcount; i++) {


        FD_SET(sockets[i].Scksas, &read_mask);

        FD_SET(sockets[i].Scksas, &write_mask);

        FD_SET(sockets[i].Scksas, &excep_mask);

   }

       /* Wait up to five seconds. */
       tv.tv_sec = 5;
       tv.tv_usec = 0;

       retval = select(1, &rfds, NULL, NULL, &tv);
       /* Don't rely on the value of tv now! */

       if (retval == -1)
           perror("select()");
       else if (retval)
           printf("Data is available now.\n");
           /* FD_ISSET(0, &rfds) will be true. */
       else{

           printf("No data within five seconds.\n");

           /*
             Handle timed out socket, but which one ?
           */
       }
       exit(EXIT_SUCCESS);
   }

How should i determine which soket timed-out?

Upvotes: 1

Views: 1313

Answers (3)

mark
mark

Reputation: 5469

More specifically, select() returns 0 if NONE of the sockets are selected in the specified timeout. If the return is a positive number, it's the number of sockets that are set (negative return is select error). The proper way to know which socket is set and where, is to use FD_ISSET on each socket, on each set, e.g.

if ( 0 != FD_ISSET( sock, &efds ) )...

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409442

The problem is that you can't use select et al., because their timeout is for the whole set not single sockets.

There are three easy solutions to find out individual sockets who had no communication for a certain time period.

  1. Simplest is probably to keep a structure for each socket, and in this structure have a time of last communication. At regular intervals you check this time for all sockets, and if the time is to long ago then close the connection.

  2. The other solution is to have a "keep alive" message being in the protocol. At regular intervals send an "are you alive" message on all sockets. If you don't get a "I am alive" reply within some timeout then the connection could be considered stale and you can close it.

  3. Use separate threads or processes for each socket. Then you can use select because you only have a single socket in the set.

Upvotes: 2

user207421
user207421

Reputation: 311039

I already know that if a particular socket times out, select() returns 0.

No you don't. It returns zero if all the sockets time out. In that case it's easy: close them all.

If it returns non-zero, you have to process all the FDs in the read/write FD sets; then you can process all the FDs that weren't in those sets. You would need to maintain the last I/O times for all FDs and check in that loop whether any were over your timeout limit.

Upvotes: 0

Related Questions