TCP套接字:如何在服务器上使用FD_ISSET()来检测客户端的发送数据?

时间:2019-02-19 23:32:14

标签: tcp unix-socket

我有一个服务器,该服务器具有与对应的客户端连接的多个套接字,我想使用select()来检测客户端是否正在向对应的套接字发送数据。我的代码是:

fd_set player_fd_set;
  FD_ZERO(&player_fd_set);
  int max_fd = players[0].connected_socket_on_master;
  for (int i = 0; i < num_players; i++) {
    FD_SET(players[i].connected_socket_on_master, &player_fd_set);
    if (players[i].connected_socket_on_master > max_fd) {
      max_fd = players[i].connected_socket_on_master;
    }
  }

  select(max_fd + 1, &player_fd_set, NULL, NULL, NULL);

  for (int i = 0; i < num_players; i++) {
    printf("Check fd # %d\n", i);
    if (FD_ISSET(players[i].connected_socket_on_master, &player_fd_set)) {
      printf("Coming from player # %d\n", i);
      ssize_t recvStatus = recv(players[i].connected_socket_on_master,
                                potato.trace, sizeof(potato.trace), 0);
      if (recvStatus == -1) {
        printf("Error: Could not recv final potato from player # %d\n", i);
        exit(EXIT_FAILURE);
      }
      break;
    }
  }

似乎FD_ISSET()首次进入for循环后立即返回。我从stackoverflow中的另一个问题中了解到,select()是级别触发的,而不是边缘触发的,那么如何检测从套接字接收的数据?

谢谢!

1 个答案:

答案 0 :(得分:1)

您的fd_set设置很好,但是在进入阅读循环之前,您没有检查select()的{​​{1}}的返回值。

您的阅读循环在错误的位置调用了> 0,实际上它根本不应该在调用break 。一旦任何客户端发送数据,您将退出循环,而忽略其他可能发送了等待读取数据的客户端。您需要遍历每个处于可读状态的套接字的整个break读数。

如果fd_set失败,则您的阅读循环不应调用exit()。只需recv()发生故障的套接字,将其从close()中删除,然后继续进行下一个循环迭代即可。

如果players[]返回-1,请确保检查recv()中的errnoEWOULDBLOCK,因为它们不是致命错误。另外,如果EAGAIN返回0,则表明客户端已断开连接。

尝试更多类似的方法:

recv()