从多个套接字阻塞 select()

问题描述 投票:0回答:3

Unix/C 问题在这里。

我有多个套接字,我正在尝试轮询周期性数据。我不想 select 无限期地等待,所以我有一个超时,并且我正在循环中运行。我发现一旦套接字准备好读取,它就始终准备好读取。例如,当没有从任何套接字读取数据时,我无法让 select 进入睡眠状态。

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

似乎在我第一次读取之后,1 秒超时不再适用,并且套接字始终“准备好读取”,即使有 0 字节可用。我怎样才能让 select 进入睡眠状态,直到数据进入(一秒钟,或者将最后一个参数切换为 NULL,无限期地等待套接字上的数据进入?)

输出:

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

注意:为了清晰起见,更新了代码 根据 @yvesBraumes 的建议进行了更新 - 仍然不起作用。

c unix blocking posix-select
3个回答
6
投票

如果检测到连接关闭,请从 fd 集中删除该套接字,否则

select
将报告它们(
Socket 4 hung up
).. select 不是边缘触发的,如果不处理该事件,它是又要举报了。


5
投票

事实上,如果recv返回0(而不是-1,errno=EWOULDBLOCK),则套接字被关闭。您也应该对其调用

close()
,并将其从
select()
调用中取出。否则会一直处于WAIT1状态,每次都会释放
select()


0
投票

您错误地使用了 FD_ISSET。您需要将套接字 ID 传递给“fd”参数,而不是索引:

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

需要

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

同样适用于

recv

© www.soinside.com 2019 - 2024. All rights reserved.