0

这是我正在使用的代码。每当我向 Stdin 写东西时,它都可以工作,但它不适用于套接字。它无法进入 Socket 的循环。我是套接字编程的新手。

void HandleConnection(int socket)
{
  fd_set rfd;
  struct timeval tv;
  int retval;

  printf("%d",socket);
  MakeNonBlocking(socket);

  /* Watch stdin (fd 0) to see when it has input. */
  FD_ZERO(&rfd);

  while(1)
  {
    FD_SET(STDIN, &rfd);
    FD_SET(socket, &rfd);

    /* Wait up to five seconds. */
    tv.tv_sec = 50;
    tv.tv_usec = 0;

    retval = select(2, &rfd,NULL, NULL, &tv);
    if(retval == 0)
    {
        printf("No data within fifty seconds.\n");
        exit(1);
    }
    if(FD_ISSET(socket,&rfd))
    {
        printf("socket wala\n");
        recieve_message(&socket);
        send_message(&socket);
    }
    if(FD_ISSET(STDIN,&rfd))
    {
        printf("stdin wala\n");
        recieve_message(&socket);
        send_message(&socket);
    }
  }
}
4

2 回答 2

1

看来您不了解如何使用nfds参数 to select()。手册页明确地解决了这个问题:

在每组中检查第一个 nfds 描述符;即,检查描述符集中从 0 到 nfds-1 的描述符。(例如:如果您设置了两个文件描述符“4”和“17”,nfds 不应为“2”,而应为“17 + 1”或“18”。)

所以这里是你应该如何重写你的代码。

int maxfd = (socket > STDIN ? socket : STDIN) + 1; /* select() requires the number of FDs to scan, which is max(fds)+1 */

while(1){

  FD_ZERO(&rfd); /* This needs to be done each time through the loop */
  /* Watch stdin (fd 0) to see when it has input. */
  FD_SET(STDIN, &rfd);
  FD_SET(socket, &rfd);

  /* Wait up to five seconds. */
  tv.tv_sec = 50;
  tv.tv_usec = 0;

  retval = select(maxfd, &rfd,NULL, NULL, &tv);
  if(retval == 0)
    {
      printf("No data within fifty seconds.\n");
      exit(1);
    }
  if(retval == -1) /* Check for error */
    {
      perror("Error from select");
      exit(2);
    }
  if(FD_ISSET(socket,&rfd))
    {
      printf("socket wala\n");
      recieve_message(&socket);
      send_message(&socket);
    }
  if(FD_ISSET(STDIN,&rfd))
    {
      printf("stdin wala\n");
      recieve_message(&socket);
      send_message(&socket);
    }

 }
于 2013-05-12T10:59:55.390 回答
1
  1. FDZERO 必须在循环内的 FDSET 之前
  2. select(2, ...) 应该是 select(highest filedescriptor +1, ...)。
  3. 当 select 返回时,您应该检查是否有负值以防出错
  4. 您应该考虑使用 pselect 而不是 select。
  5. 在重新初始化之前清除电视。
于 2013-05-12T11:00:46.840 回答