【问题标题】:Non-blocking select()?非阻塞选择()?
【发布时间】:2015-11-22 07:41:16
【问题描述】:

我正在尝试实现简单的网络游戏(客户端 - 服务器),它使用 UDP 通过网络传输游戏事件,并且我运行良好,但现在我想在同一个控制台应用程序中通过 tcp 添加到游戏聊天.我尝试使用select() 和非阻塞主套接字来实现多客户端聊天。聊天作为独立应用程序运行,但我无法将其组合在一起。

基本上我的服务器循环如下所示:

while(true)
{
    sendUDPdata()
    ...

    while(true)
    {
        receiveUDPdata()
    }
}

问题是当我想像这样将聊天添加到服务器的主循环(处理 UDP)时:

while(true)
{
    HandleTCPConnections();

    sendUDPdata();
    ...

    while(true)
    {
        receiveUDPdata();
    }
}

HandleTCPConnections() 中调用select() 会阻塞整个服务器。有什么办法可以处理吗?

【问题讨论】:

  • select() 有超时。您可以使用 0 秒的超时来轮询请求的套接字并立即退出而不阻塞。
  • @RemyLebeau 但是他做了什么?他不能再打电话给select
  • @DavidSchwartz 为什么不呢?他可以循环调用select(),同时请求TCP和UDP套接字。如果 TCP 套接字报告它有数据等待,请读取它。如果 UDP 套接字报告它有数据等待,读取它。 select() 的主要设计之一是在单个线程中处理多个套接字的 I/O。
  • @RemyLebeau 你的意思是他只是在循环中一遍又一遍地调用select,即使他无事可做也完全消耗核心?!
  • @DavidSchwartz:我建议如果 OP 想要在将 TCP 注入到混合中时保留他现有的 UDP 循环,他可以使用select() 在 UDP 循环迭代之间轮询 TCP 套接字。最好重新编写代码,让select() 同时监控 TCP 和 UDP 套接字,并让它在任何套接字有数据要处理时报告。在没有超时的情况下,select() 将使调用线程进入休眠状态,直到任何套接字准备好做某事。使用非零超时,如果没有套接字更快地唤醒它,线程将休眠直到超时过去。

标签: c++ sockets tcp udp


【解决方案1】:

有两种很好的方法来做到这一点:

  1. 使用线程。有一个线程来处理你的 TCP 套接字和一个线程来处理你的 UDP 套接字。

  2. 使用反应器。 UDP 代码和 TCP 代码都向反应器注册它们的套接字。反应器阻塞所有套接字(通常使用poll)并在该套接字上发生活动时调用适当的代码。

如果您不想重新发明轮子,可以使用这两个选项(例如 libeventboost.asio)的许多库。

【讨论】:

    【解决方案2】:

    select 在您的情况下,如果套接字没有可用数据,则为阻塞调用。

    您的聊天可以与服务器一起运行,也可以与其并行运行:您已经有了第一个案例;其次,您最好选择一个单独的线程来处理聊天。 C++ 有<thread>,你可能想看看。

    在这种情况下,单独的线程更容易实现,因为您有单独的连接,因此需要单独的套接字,否则需要注意并发访问。

    【讨论】:

      猜你喜欢
      • 2015-05-05
      • 2013-12-28
      • 2014-03-08
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-06
      相关资源
      最近更新 更多