Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 非阻塞选择()?_C++_Sockets_Tcp_Udp - Fatal编程技术网

C++ 非阻塞选择()?

C++ 非阻塞选择()?,c++,sockets,tcp,udp,C++,Sockets,Tcp,Udp,我正在尝试实现简单的网络游戏(客户机-服务器),它使用UDP通过网络传输游戏事件,我已经很好地实现了这一点,但现在我想在同一控制台应用程序中通过tcp添加到游戏聊天中。我尝试使用select()和非阻塞主套接字实现多客户端聊天。聊天是作为独立的应用程序工作,但我有问题把它放在一起 基本上,我的服务器循环如下所示: while(true) { sendUDPdata() ... while(true) { receiveUDPdata()

我正在尝试实现简单的网络游戏(客户机-服务器),它使用UDP通过网络传输游戏事件,我已经很好地实现了这一点,但现在我想在同一控制台应用程序中通过tcp添加到游戏聊天中。我尝试使用
select()
和非阻塞主套接字实现多客户端聊天。聊天是作为独立的应用程序工作,但我有问题把它放在一起

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

while(true)
{
    sendUDPdata()
    ...

    while(true)
    {
        receiveUDPdata()
    }
}
while(true)
{
    HandleTCPConnections();

    sendUDPdata();
    ...

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

while(true)
{
    sendUDPdata()
    ...

    while(true)
    {
        receiveUDPdata()
    }
}
while(true)
{
    HandleTCPConnections();

    sendUDPdata();
    ...

    while(true)
    {
        receiveUDPdata();
    }
}

handletcpcconnections()
中调用
select()
,会阻塞整个服务器。有没有办法处理这个问题?

有两个好办法:

  • 使用线程。有一个线程来处理TCP套接字,还有一个线程来处理UDP套接字

  • 使用反应堆。UDP代码和TCP代码都向反应器注册它们的套接字。反应器阻塞所有套接字(通常使用
    轮询
    ),并在该套接字上发生活动时调用相应的代码


  • 对于这两个选项(如和),有很多库可供您使用,如果您不想重新发明轮子。

    有两种好方法:

  • 使用线程。有一个线程来处理TCP套接字,还有一个线程来处理UDP套接字

  • 使用反应堆。UDP代码和TCP代码都向反应器注册它们的套接字。反应器阻塞所有套接字(通常使用
    轮询
    ),并在该套接字上发生活动时调用相应的代码


  • 对于这两个选项(如和),有很多库可供您使用,如果您不想重新发明轮子。

    select
    在您的情况下,如果套接字中没有可用数据,则是一个阻塞调用

    您的聊天可以与服务器一起运行,也可以与服务器并行运行:您已经有了第一个案例;对于第二个问题,您最好使用一个单独的线程来处理聊天。C++有<代码> <代码>,你可能想看一下。


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

    select
    在您的情况下,如果套接字中没有可用数据,则是一个阻塞调用

    您的聊天可以与服务器一起运行,也可以与服务器并行运行:您已经有了第一个案例;对于第二个问题,您最好使用一个单独的线程来处理聊天。C++有<代码> <代码>,你可能想看一下。


    在这种情况下,单独的线程更容易实现,因为您有一个单独的连接,因此需要单独的套接字来进行并发访问。

    select()
    有一个超时。您可以使用0秒的超时轮询请求的套接字并立即退出而不阻塞。@RemyLebeau但他会怎么做?他不能再调用
    select
    。@DavidSchwartz为什么不呢?他可以在循环中调用
    select()
    ,同时请求TCP和UDP套接字。如果TCP套接字报告有数据等待,请读取它。如果UDP套接字报告有数据等待,请读取它。
    select()
    的主要设计之一是在一个线程中处理多个套接字的I/O。@RemyLebeau你是在建议他在一个循环中反复调用
    select
    ,即使他没有工作做,也会完全消耗内核@DavidSchwartz:我的建议是,如果OP希望在将TCP注入混合时保留现有的UDP循环,他可以在UDP循环迭代之间使用
    select()
    轮询TCP套接字。最好重新编写代码,让
    select()
    同时监视TCP和UDP套接字,并让它在任何套接字有数据要处理时报告。如果没有超时,
    select()
    将使调用线程处于休眠状态,直到任何套接字准备好执行某项操作为止。对于非零超时,如果没有套接字提前唤醒线程,则线程将一直休眠,直到超时结束。
    select()
    有一个超时。您可以使用0秒的超时轮询请求的套接字并立即退出而不阻塞。@RemyLebeau但他会怎么做?他不能再调用
    select
    。@DavidSchwartz为什么不呢?他可以在循环中调用
    select()
    ,同时请求TCP和UDP套接字。如果TCP套接字报告有数据等待,请读取它。如果UDP套接字报告有数据等待,请读取它。
    select()
    的主要设计之一是在一个线程中处理多个套接字的I/O。@RemyLebeau你是在建议他在一个循环中反复调用
    select
    ,即使他没有工作做,也会完全消耗内核@DavidSchwartz:我的建议是,如果OP希望在将TCP注入混合时保留现有的UDP循环,他可以在UDP循环迭代之间使用
    select()
    轮询TCP套接字。最好重新编写代码,让
    select()
    同时监视TCP和UDP套接字,并让它在任何套接字有数据要处理时报告。如果没有超时,
    select()
    将使调用线程处于休眠状态,直到任何套接字准备好执行某项操作为止。对于非零超时,如果没有套接字提前唤醒线程,线程将一直休眠到超时结束。