【问题标题】:How can I skip reading from a connected client in C?如何跳过从 C 中连接的客户端读取?
【发布时间】:2022-01-12 22:48:50
【问题描述】:

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

【问题讨论】:

  • 听起来像XY problem。为什么你认为客户需要跳过阅读?用如此简短的描述很难确定任何事情。但通常客户端会做它需要做的任何事情,服务器会独立处理超时。
  • 作为一般规则,当从一个不可查找的文件(如套接字)中消费数据时,必须读取每个字节才能读取任何后续字节。您对所读内容做什么由您自行决定,如果有的话,您可以自行决定,但不,您不能按照您的意思跳过此类数据源的读取。
  • 跳过读取调用的最佳方法是使用非阻塞读取。并记账。
  • @wildplasser,我看不出非阻塞读取如何提供与问题相关的任何意义上的 skipping 读取调用。避免阻塞不会跳过读取,甚至它本身也不会提供超时。
  • @lucimaster 您的描述听起来像是您想跳过客户端的读取。但是您的最后一条评论更清楚地表明您要跳过的是服务器端阅读。在这种情况下,select 会超时。

标签: c networking pthreads


【解决方案1】:

关于服务器跳过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()的技术要求。功能。

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

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

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

  • 响应可能在网络上被分成多个部分,因此响应的开头可能会在超时内到达,但结尾不会,甚至可能根本不会。

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

【讨论】:

    猜你喜欢
    • 2011-06-12
    • 2013-02-04
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多