0

In C, suppose I have a server application. The socket is setup properly and has been bound to a local port, and the listen() function has been called without error.

Code like this:

    //obtain a connection.
    int connection;
    struct sockaddr_storage sender;
    socklen_t addr_size = sizeof(sender);
    if((connection=accept(sockfd, (struct sockaddr*)&sender, &addr_size))==-1)
            {close(sockfd); return -1; }
    if(close(sockfd)==-1){
            close(connection);
            return -1;
    }
    else
            return connection;

Successfully obtains a connection file descriptor through which data can be read from a client.

My application requires that the server wait for a finite amount of time, and then go off and do other things if no connection is made. Further, at most one connection will be accepted. Accept() is a blocking system call, but I would like to avoid blocking.

There seem to be many different ways to address this:

  • A SE question suggests using select to solve this, but select is designed for monitoring many file handles at once, and seems like overkill here.

  • Another question suggests modifying the socket to be non-blocking and then checking in a loop whether or not a connection was made. This would work also, but doesn't seem very nice because I do want to block - just not forever.

  • In other languages I have seem people use SIGALARM and the alarm() command to prevent blocking, but my application has several threads, and this seems like an error-prone solution.

  • In some other languages (Java?) I think there's a timeout argument that can be passed to accept which accomplishes this. That would be ideal here, but I can't seem to find a similar function for sockets in C.

Is there a nicer way to address this? It seems like the sort of thing someone else would have figured out already. If there isn't a nicer way, which of the solutions mentioned above is most appropriate? I'm leaning toward making the socket non-blocking, but it seems to introduce a large amount of extra cruft.

Community
  • 1
  • 1
John Doucette
  • 4,370
  • 5
  • 37
  • 61
  • 3
    This is exactly what `select()` is for...waiting some amount of time for activity on one or more file descriptors. Call `select()` with a timeout and you're got what you want. – larsks Nov 15 '12 at 17:41
  • 1
    `select()` is exactly what you need. Wrap it in a little function and it won't look like overkill either. – moooeeeep Nov 15 '12 at 17:45

1 Answers1

1

When using select remember to always make your file-descriptor non blocking with fcntl(), otherwise a client might initiate a connection, select would return, the client might terminate and your server would be blocked forever in the accept().

After a successful accept you might turn the file-descriptor into blocking mode again if your program works this way.

LtWorf
  • 7,286
  • 6
  • 31
  • 45