STDIN阻止激活其他文件描述符

时间:2013-11-02 21:12:49

标签: c++ sockets network-programming stdin posix-select

编写以下程序是为了接收客户端的消息并从键盘读取用户输入:

FD_ZERO(&masterfds);
FD_SET(udp_con, &masterfds);
FD_SET(0, &masterfds);
maxfds = udp_con;
while(exit == false)
{ 
  FD_ZERO(&readfds);
  readfds = masterfds;

  selectFunc = select(maxfds+1, &readfds, NULL, NULL, &tv);
  if(selectFunc < 0) {
    message("error in select");
    exit = true;
  } else {
    // The server has received something from a client
    for(i = 0; i <= maxfds; i++) {
      if(FD_ISSET(i, &readfds)) {
        if(FD_ISSET(0, &readfds)) {
          fgets(userInput, sizeof(userInput), stdin);
          int len = strlen(userInput) - 1;
          if (userInput[len] == '\n') {
            userInput[len] = '\0';
          }
          cout<<"The user said: "<<userInput<<endl;
        } else if(i == udp_con) {
          cout<<"Datagram received"<<endl;
          // After reading the user input, it never reaches here
        }
      }
    }
  }
}

问题在于,当我按下键盘上的“enter”键并激活“0”文件描述符时,程序将永远不会激活任何其他文件描述符并锁定“0”文件描述符。我该如何修复这个错误?

1 个答案:

答案 0 :(得分:1)

使用FD_CLR(0, readfds)对其进行测试后,您需要FD_ISSET(0, &readfds),否则总是接受该分支。

但您可以通过重写算法来简化算法。养成格式化代码以使其易于阅读的习惯是个好主意。

FD_ZERO(&masterfds);
FD_SET(udp_con, &masterfds);
FD_SET(0, &masterfds);
maxfds = udp_con;

while (true) {
  readfds = masterfds;

  selectFunc = select(maxfds + 1, &readfds, NULL, NULL, &tv);
  if (selectFunc < 0) {
    message("error in select");
    break;
  }

  // Check for input on stdin (fd 0).
  if (FD_ISSET(0, &readfds)) {
    fgets(userInput, sizeof(userInput), stdin);
    int len = strlen(userInput) - 1;
    if (userInput[len] == '\n') {
      userInput[len] = '\0';
    }
    cout << "The user said: '" << userInput << "'" << endl;
  }
  // Check for input on the udp_con fd.
  if (FD_ISSET(udp_con, &readfds)) {
    cout << "Datagram received" << endl;
  }
}