我怎样才能跳过从 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()
、 等的技术要求。函数。
请注意,它比这更复杂,但是。至少还有这些额外的考虑因素:
您需要为客户端断开连接的情况做好准备。
如果客户端的响应到达得太晚,那么您将需要阅读该响应并(大概)丢弃它,然后才能处理来自同一客户端的任何后续响应。
响应可能会在线路上分成多个部分,因此响应的开头可能会在超时内到达,但结尾不会,也许根本不会。
为了稳健性,您需要处理在时间到期之前等待被信号中断的情况。在这种情况下,您可能希望恢复等待,但不重新开始超时。
我正在开发一个带有线程的 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()
、 等的技术要求。函数。
请注意,它比这更复杂,但是。至少还有这些额外的考虑因素:
您需要为客户端断开连接的情况做好准备。
如果客户端的响应到达得太晚,那么您将需要阅读该响应并(大概)丢弃它,然后才能处理来自同一客户端的任何后续响应。
响应可能会在线路上分成多个部分,因此响应的开头可能会在超时内到达,但结尾不会,也许根本不会。
为了稳健性,您需要处理在时间到期之前等待被信号中断的情况。在这种情况下,您可能希望恢复等待,但不重新开始超时。