Block select () from multiple sockets

Unix / C question here.

I have several sockets that I am trying to poll for periodic data. I do not want to choose to wait indefinitely, so I have a timeout in place and I am running in a loop. I found that after the socket is ready to read, it is always ready to read . As in, I cannot choose to sleep when there is no data to 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 1st timeout is no longer applied and the socket is always “ready to read”, even if 0 bytes are available. How can I get a choice for sleep until the data arrives (within one second or by switching the final argument to NULL, vaguely expecting the data to arrive on the socket?)

Exit:

 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... 

Thanks,

Note. Code updated for clarity Updated based on @yvesBraumes suggestions - it still doesn't work.

+6
source share
3 answers

If you find that the connection is closed, remove the socket from the fd set, otherwise select will report it ( Socket 4 hung up ). select does not fire around the edge, if you do not handle the event, it is going to report it again.

+5
source

In fact, if recv returns 0 (rather than -1, with errno = EWOULDBLOCK), the socket closes. You should also call it close() and get it out of the select() call. Otherwise, it will remain in WAIT1 and unlock select() each time.

+4
source

You are using FD_ISSET incorrectly. You need to pass the socket id to the "fd" parameter, not the index:

 if (FD_ISSET(i, &read_fds))... 

should be

 if (FD_ISSET(sockfd[i], &read_fds))... 

Similarly with recv .

0
source

Source: https://habr.com/ru/post/910031/


All Articles