我怎样才能跳过从 C 中连接的客户端读取?

How can I skip reading from a connected client in C?

我正在开发一个带有线程的 TCP 客户端服务器应用程序,客户端轮流向服务器发送消息(类似于回合制游戏)。 服务器向客户端发送消息,但客户端有 n 秒的响应时间。如果客户端没有及时响应,服务器应该在不关闭连接的情况下转到下一个客户端。有没有办法跳过来自服务器的 read() 调用?

您关于服务器跳过 read() 调用的意思并不十分清楚,但我认为您是在谈论实现您描述的响应超时。一种常见的方法是使用 select() 函数,它允许您等待指定的时间量让文件描述符准备就绪。然后,您可以根据 select() 是否发出所需文件描述符已准备就绪的信号来选择是 read() 还是转到下一个客户端。

非常粗略地说,可能是这样的:

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>

// ...

    fd_set read_fds;

    FD_ZERO(&read_fds);
    FD_SET(client_fd, &read_fds);

    struct timeval timeout = { .tv_sec = 5, .tv_usec = 0 };

    int num_ready = select(client_fd + 1, &read_fds, NULL, NULL, &timeout);

    if (num_ready == -1) {
        // handle error ...
    } else if (num_ready == 0) {
        // handle timeout ...
    } else if (num_ready == 1) {
        // handle client response ...
    } else {
        // should not happen
        assert(0);
    }

您还可以考虑具有类似行为的 select() 的替代方案,例如 poll()epoll_wait()。此外,您可能会发现与此相关的将客户端套接字配置为非阻塞 I/O 是有利的,尽管这不是使用 select() 等的技术要求。函数。

请注意,它比这更复杂,但是。至少还有这些额外的考虑因素:

  • 您需要为客户端断开连接的情况做好准备。

  • 如果客户端的响应到达得太晚,那么您将需要阅读该响应并(大概)丢弃它,然后才能处理来自同一客户端的任何后续响应。

  • 响应可能会在线路上分成多个部分,因此响应的开头可能会在超时内到达,但结尾不会,也许根本不会。

  • 为了稳健性,您需要处理在时间到期之前等待被信号中断的情况。在这种情况下,您可能希望恢复等待,但不重新开始超时。