Unix/C question here.
I have multiple sockets that I am trying to poll for periodic data. I don't want select to wait indefinitely so I have a timeout in place and I'm running in a loop. I have found that once a socket is ready to read, it is always ready to read. As in, I cannot have select go to sleep when there is no data to be read from any of the sockets.
for (i = 0; i < n_connections; i++) {
FD_SET( sockfd[i], &master );
if (sockfd[i] > fdmax)
fdmax = sockfd[i];
}
for(;;) {
int nready = 0;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
read_fds = master;
if ( (nready = select(fdmax+1, &read_fds, NULL, NULL, NULL)) == -1 ) {
fprintf( stderr, "Select Error\n" );
return FAILURE;
}
printf( "Number of ready descriptors: %d\n", nready );
for (i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) {
if (( nbytes = recv(i, buf, sizeof(buf), 0)) <= 0 ) {
if (nbytes == 0) {
//connection closed
printf("Socket %d hung up\n", i );
}
else {
fprintf( stderr, "Recv Error %d\n", nbytes);
}
}
else {
printf( "Data Received on %d: %s\n", i, buf );
}
}
} // end file descriptor loop
It seems that after my first read, the 1 second timeout no longer applies and the socket is always "ready to read", even if there are 0 bytes available. How can I get select to sleep until data comes in (for the one second, or by switching the final argument to NULL, indefinitely waiting for data to come in on the socket?)
Output:
Number of Ready Descriptors: 2
Data Received on 4: GreetingsChap
Data Received on 5: HiMatengsChap
Loop...
Number of Ready Descriptors: 2
Socket 4 hung up
Socket 5 hung up
Loop...
Number of Ready Descriptors: 2
Socket 4 hung up
Socket 5 hung up
Loop...
Thank you,
Note: Code updated for clarity Updated based on @yvesBraumes suggestions - still doesn't work.
By using the select() call, you do not issue a blocking call until you know that the call cannot block. The select() call can itself be blocking, nonblocking, or, for the macro API, asynchronous.
listen() is non-blocking.
The first argument is the highest file descriptor plus one. Thus, if we pass two file descriptors with values 2 and 10, then the nfds parameter should be 10 + 1 or 11 and not 2. The maximum number of sockets supported by select() has an upper limit, represented by FD_SETSIZE (typically 1024).
You can use the select() call to pass a bit set containing the socket descriptors for the sockets you want checked. The bit set is fixed in size using one bit for every possible socket. Use the nfds parameter to force select() to check only a subset of the allocated socket bit set.
If you detect that a connection is closed, remove the socket from the fd set, otherwise select
is going to report them (Socket 4 hung up
).. select is not edge triggered, if you don't handle the event, it's going to report it again.
Indeed, if recv returns 0 (and not -1, with errno=EWOULDBLOCK), the socket is closed. You should call close()
on it as well, and take it out of the select()
call. Otherwise it will remain in WAIT1 and release select()
each time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With