【问题标题】:Notify a thread when I/O is possible on a socket当套接字上可以进行 I/O 时通知线程
【发布时间】:2019-04-03 09:26:42
【问题描述】:

我正在构建一个在线多人游戏服务器。目前的网络架构非常简单:acceptor 线程是一个无限循环,它只是等待accept()。如果它获得了连接,那么它会设置所有内容并生成一个线程来处理与该客户端的通信。

我的问题出现在我收到登录数据包后,因为线程应该等到有任何数据要读取(一个新的数据包,比如“攻击这个生物”,到达)。我知道标志 O_ASYNC 会使系统触发 SIGIO,但由于线程在 linux 上具有相同的 PID,因此信号会被整个进程捕获。

有没有一种有效的方法可以在有数据要读取时通知线程,以便知道何时解析数据包并最终调用工作线程来处理命令?

编辑:忘了提到我将套接字设置为 O_NONBLOCK 所以 read() 不会阻塞,因为客户端线程可能随时被另一个线程调用。

【问题讨论】:

  • 如果您为客户端生成一个新线程,该线程可以等待/阻塞,直到通过在套接字上调用 read()/recv() 或类似方法获得可用数据。
  • 为什么?当 I/O 是可能的,特别是当有数据要读取时,它会在没有阻塞的情况下完成。你需要线程做什么?
  • @user207421 我更新了问题。客户端线程不能在读取时阻塞,因为它可能随时被工作线程/主线程调用
  • 阅读我写的内容,并尝试自己理解。如果您使用的是非阻塞模式,则客户端线程不能阻塞根本,根据定义,如果您使用的是非阻塞模式,则您不需要需要客户端线程。 完全阻塞模式, 并且特别是如果您将 I/O 关闭“有数据要读取”。您还需要澄清您认为从另一个线程“调用”一个线程的实际含义。
  • @user743414 实际上,我并没有在客户端连接时创建线程。我在int8_t[0x44C0000] 上的游戏服务器开始时分配内存,当新的客户端线程启动时,我只需使用pthread_attr_setstack 分配此内存(0x44C)的一部分。这样我可以管理多达 1100 个同时连接并避免 pthread_create 开销

标签: c multithreading sockets


【解决方案1】:

使用select()epoll()(在Linux 上)或kqueue(在BSD 上)。

【讨论】:

    【解决方案2】:

    假设您使用的是 Linux。 我建议您直接删除线程并开始使用 epoll。 epoll 可以获取多个文件描述符并监视它们。

    你可以从这里开始:https://kovyrin.net/2006/04/13/epoll-asynchronous-network-programming/ 或在这里:http://man7.org/linux/man-pages/man7/epoll.7.html

    【讨论】:

    • 在我的工作线程上使用 epoll 并在可以 I/O 时使用 pthread_kill 向客户端线程触发 SIGIO 是否有意义?
    • 其实你不应该在你的主线程上使用 epoll 并且当套接字上有数据要读取时可能会启动一个新线程。但我不建议在您的情况下使用线程。
    猜你喜欢
    • 2013-12-17
    • 1970-01-01
    • 2022-01-05
    • 2014-05-22
    • 2018-05-05
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    相关资源
    最近更新 更多