I would like to have a server that connects to one client at a time, ignoring connection request when connected to a given client.
I would also liked to avoid the server to get locked when listening for the first client, so that the program can be terminated cleanly.
Apparently, sockets can be made non blocking: http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#blocking
I created my socket accordingly (error management code removed for clarity)
int sockfd;
struct sockaddr_in self;
sockfd = socket(AF_INET, SOCK_STREAM, 0));
fcntl(sockfd, F_SETFL, O_NONBLOCK); // making this socket non blocking
bzero(&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(port);
self.sin_addr.s_addr = inet_addr("127.0.0.1"); // allowing connection from localhost only.
bind(sockfd, (struct sockaddr*)&self, sizeof(self));
From that point, I am not sure how to manage a timeout. The following code does not work, but gives an idea what I would like to achieve.
int client_found = 0;
while ( no_stop_signal && client_found==0 ) {
listen(sockfd,1);
if ( ** something that tells me nobody was requesting connection ** ) {
usleep(10);
} else {
client_found = 1;
}
}
Any solution I found so far were concerned about situation more complex than mine (i.e. not ignoring clients once one had been found) and seemed unnecessarily complicated.
EDIT (after accepting answer):
Based on the accepted answer, here the code I came with:
static inline int wait_for_client_to_connect(int sockfd, int* server_run){
int client_found = 0;
int clientfd = 0;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
if ( listen(sockfd,1) != 0 ) return -1;
while ( client_found==0 && *server_run==1 ) {
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
if ( clientfd < 0 ) {
clientfd = 0;
if (errno==EAGAIN || errno==EWOULDBLOCK) usleep(10); // nobody connected, wait for request
else return -1; // something wrong, send error
} else { // client found, configuring socket and exit
client_found=1;
int nodelay_flag = 1;
setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay_flag, sizeof(int)); // disable nagle algorithm
}
}
return clientfd;
}
This works, but according to comments and answer, this is not the way to go (apparently a clean way would have something to do with signals ...)