Como usar o select() nos 'sockets' correctamente?
setup_server_socket
chamadas bind
e listen
e configura o 'socket' para o modo de não-bloqueio.
os seguintes blocos de código na chamada select
parece, não avançando para FD_ISSET
. Tentei ligar um cliente e parece ter sucesso, mas nunca devolve nada.
...
int listenfd = setup_server_socket( serverPort );
if( -1 == listenfd )
return 1;
fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
// loop forever
while( 1 )
{
if (select(fdmax+1, &read_fds, NULL,NULL,NULL) == -1){
perror("select");
exit(4);
}
for (int i = 0; i<= fdmax; i++){
printf("Testing: %d, %d\n", i, FD_ISSET(i,&read_fds));
}return 0;
...
2 answers
Leia várias vezes seleccione(2), poll (2) (BTW, você deve preferir poll
ao obsoleto select
, que não lida com descritores de ficheiros maiores que __FD_SETSIZE
, ou seja, 1024 no meu sistema Linux/Debian/x86-64).
Depois:
fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
FD_SET(listenfd, &read_fds);
Deve ir para dentro o laço while(1)
, antes de chamar select
. BTW, eu recomendo usar poll
em vez de select
Leia também sobre o problema de C10k
Não te esqueças que está a mudar de ideias.fd_set
- s (e normalmente quer que eles não estejam vazios)...
Talvez usar strace(1)
Leia também programação Linux avançada (é um livro livre que você também pode ler no papel, ou baixar de vários outros lugares, por exemplo isto etc...)
Aqui está um exemplo (aparado) de usar select ()
INT32 selectStatus; /* select() return code */
char tempreport[ 256 ] = {'\0'};
struct timeval tv;
fd_set fdread;
//fd_set fdwrite;
//fd_set fdexcep;
// note:
// must try to read report until no report available
// so have latest report in buffer
do
{
/* Note: timeout must be (re)set every time before call to select() */
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&fdread);
FD_SET( FD, &fdread );
selectStatus = select(FD+1, &fdread, NULL, NULL, &tv);
switch( selectStatus )
{
case -1:
....
break;
case 0:
// timeout, I.E. nothing to read
....
break;
default: /* available to read */
memset(tempreport, 0x00, sizeof(tempreport) );
readStatus = read_UDP_socket( FD, tempreport, sizeof(tempreport), &readCount );
break;
} // end switch( selectStatus )
} while( (0 < selectStatus)&&(eRS_Success == readStatus ) );
// exit loop on select timeout or select error or read failure
Notas:
eRS_Success is an entry from an enum used for various return codes
read_UDP_socket() is a local function