套接字无法正常工作的文件描述符

时间:2013-05-12 10:44:20

标签: c sockets

这是我正在使用的代码。每当我向Stdin写东西时,它都可以工作,但它不适用于套接字。它无法进入Socket循环。我是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);
    }
  }
}

2 个答案:

答案 0 :(得分:1)

您似乎无法理解如何使用nfds 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);
    }

 }

答案 1 :(得分:1)

  1. FDZERO必须在循环内的FDSET之前进行
  2. 应选择
  3. select(2,...)(最高文件描述符+1,...)。
  4. 当选择返回时,您应该在出现错误时检查负值
  5. 您应该考虑使用pselect而不是select。
  6. 在重新初始化之前清除电视。