C++ 非阻塞选择()?
我正在尝试实现简单的网络游戏(客户机-服务器),它使用UDP通过网络传输游戏事件,我已经很好地实现了这一点,但现在我想在同一控制台应用程序中通过tcp添加到游戏聊天中。我尝试使用C++ 非阻塞选择()?,c++,sockets,tcp,udp,C++,Sockets,Tcp,Udp,我正在尝试实现简单的网络游戏(客户机-服务器),它使用UDP通过网络传输游戏事件,我已经很好地实现了这一点,但现在我想在同一控制台应用程序中通过tcp添加到游戏聊天中。我尝试使用select()和非阻塞主套接字实现多客户端聊天。聊天是作为独立的应用程序工作,但我有问题把它放在一起 基本上,我的服务器循环如下所示: while(true) { sendUDPdata() ... while(true) { receiveUDPdata()
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()
,会阻塞整个服务器。有没有办法处理这个问题?有两个好办法:
轮询
),并在该套接字上发生活动时调用相应的代码对于这两个选项(如和),有很多库可供您使用,如果您不想重新发明轮子。有两种好方法:
轮询
),并在该套接字上发生活动时调用相应的代码对于这两个选项(如和),有很多库可供您使用,如果您不想重新发明轮子。
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()
将使调用线程处于休眠状态,直到任何套接字准备好执行某项操作为止。对于非零超时,如果没有套接字提前唤醒线程,线程将一直休眠到超时结束。