简体   繁体   English

在侦听套接字上使用select()

[英]Using select() on listening socket

I want to open a port and wait for incoming connections, however I can't get select() to work. 我想打开一个端口并等待传入​​连接,但是我无法使select()正常工作。 I had it working with poll() but I need select() for portability. 我有它与poll()一起工作,但是我需要select()来实现可移植性。 What am I doing wrong? 我究竟做错了什么?

Code for waiting for the connection looks like this (I need to check for interruptions every 200ms): 等待连接的代码如下所示(我需要每200ms检查一次中断):

/* Wait for a descriptor */
int wait_for_fd(int fd){
  int waitms = 200;
  struct timeval tv;
  tv.tv_sec = 0;
  tv.tv_usec = waitms * 1000;
  fd_set rfds;
  FD_ZERO(&rfds);
  FD_SET(fd, &rfds);
  int active = 0;
  while(active == 0){
    active = select(fd+1, &rfds, NULL, NULL, &tv);
    bail_for(active < 0, "select()");
    if(pending_interrupt())
      break;
  }
  return active;
}

And then my code to actually open a port and wait for a connection: 然后我的代码实际打开一个端口并等待连接:

int open_port(int port){

  // define server socket
  struct sockaddr_in serv_addr;
  memset(&serv_addr, '0', sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(port);

  //creates the listening socket
  int listenfd = socket(AF_INET, SOCK_STREAM, 0);
  bail_for(listenfd < 0, "socket()");
  bail_for(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0, "bind()");
  bail_for(listen(listenfd, 10) < 0, "listen()");

  //each accept() is a new incoming connection
  printf("Waiting for connetion on port %d...\n", port);
  wait_for_fd(listenfd);
  int connfd = accept(listenfd, NULL, NULL);
  bail_for(connfd < 0, "accept()");
  printf("Incoming connection!\n");

  //do not allow additional client connetions
  close(listenfd);
  return connfd;
} 

However wait_for_fd() never returns (due to select always returning 0) even when a client is connecting. 但是,即使客户端正在连接, wait_for_fd()也永远不会返回(由于选择总是返回0)。

This must be on every iteration: 这必须在每次迭代中:

FD_ZERO(&rfds);
FD_SET(fd, &rfds);

Because rfds is an in/out parameter for select() . 因为rfdsselect()的输入/输出参数。 It actually tells with it which fds were affected. 它实际上告诉它哪些fds受到了影响。

According to manpage of select 根据select

On exit, the sets are modified in place to indicate which file descriptors actually changed status. 退出时,对集合进行适当的修改,以指示实际更改状态的文件描述符。 Each of the three file descriptor sets may be specified as NULL if no file descriptors are to be watched for the corresponding class of events. 如果没有文件描述符针对相应的事件类进行监视,则可以将三个文件描述符集的每一个指定为NULL。

This means, that, when you have called select and no file-descriptors have changed, no file-descriptors are set in rfds . 这意味着,当您调用select且未更改文件描述符时,不会在rfds中设置rfds Therefor you'll have to set them on each iteration 因此,您必须在每次迭代中设置它们

while(active == 0){
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);
    active = select(fd+1, &rfds, NULL, NULL, &tv);
    bail_for(active < 0, "select()");
    if(pending_interrupt())
      break;
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM