gpt4 book ai didi

c - 为什么 select 不向带有缓冲数据的文件描述符发出信号?

转载 作者:行者123 更新时间:2023-11-30 16:22:17 25 4
gpt4 key购买 nike

我有一个服务器程序,它使用 select 并设置 10 秒超时来等待多个非阻塞客户端连接上的事件。每次 select 调用发出信号表明有输入要读取时,服务器将读取并处理最多 1K 的数据。如果有要发送的响应,它就会发送。然后它会返回选择

fcntl(clientFd, F_SETFL, fcntl(clientFd, F_GETFL, 0) | O_NONBLOCK);
while (true) {
FD_ZERO(&readfds);
FD_SET(clientFd, &readfds);
timeout = (struct timeval){.tv_sec = 10};
select(clientFd + 1, &readfds, NULL, NULL, &timeout);
if (FD_ISSET(clientFd, &readfds)) {
uint8_t recv_buffer[1024];
fread(recv_buffer, 1, 1024, clientFile);
// process & maybe respond / fflush
}
}

客户端消息的范围从小(10 或 100 字节)消息到大(3-10K 消息)。客户在挂断电话之前将等待长达 30 秒的响应。当他们挂断电话时,会发送一条 10 字节的挂断消息。

正在发生的场景打破了我对 select 应该如何工作的理解。客户端发送的消息小于读取缓冲区,因此服务器读取整个消息并做出响应。然后客户端发送一条3K消息。服务器读取前 1K,然后后续的 select 调用超时。我希望 select 立即返回,并发出信号,表示如果内核有为该文件描述符缓冲的数据,则有可用的数据。客户端超时后,发送挂断消息。当挂断消息到达时,服务器突然能够选择该文件描述符,并读取客户端较大消息的第二和第三 block ,然后读取客户端较小的消息。

我非常确定这些事件的发生时间,因为 (1) 涉及较长的超时,(2) 对话的 tcpdump 确认 3K 消息作为单个 TCP 段到达。

使用pipe的简单演示程序不会表现出这种行为,另一个使用TCP套接字的简单演示也不会表现出这种行为。所以我一定在服务器程序中做了一些愚蠢的事情。我应该检查什么?

我正在检查:

  • 客户端的读FD位于select之前的读FD集中
  • 客户端的读FD是否在select后的读FD集中(不是)
  • 读取数据的大小(如果至少有那么多可用,则始终为 1K)
  • fread 的第二次调用是否会阻塞(不会。我在调试器中尝试过,并且还使用大小为 4K 的 recv_buffer 进行了不同的运行,其中阅读整条 3K 消息)
  • 通过 tcpdump 进行数据包碎片(无)

wsd

最佳答案

发布什么@n.m。说。如果他们发表评论作为答案,将会被删除:

read is a buffered I/O function. You've given up all control. You have no idea how many bytes are really being read from the underlying file descriptor. You can try using setvbuf to make your file unbuffered. – n.m.

关于c - 为什么 select 不向带有缓冲数据的文件描述符发出信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54508470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com