我正在尝试创建一个UDP广播程序来检查本地游戏服务器,但我遇到了接收端的问题。由于生存的服务器数量始终未知,因此必须具有仅在停止时退出的循环。所以在这里的代码中:
while(1) // start a while loop
{
if(recvfrom(sd,buff,BUFFSZ,0,(struct sockaddr *)&peer,&psz) < 0) // recvfrom() function call
{
cout << red << "Fatal: Failed to receive data" << white << endl;
return;
}
else
{
cout << green << "Found Server :: " << white;
cout << yellow << inet_ntoa(peer.sin_addr), htons(peer.sin_port);
cout << endl;
}
}
我希望运行这个recvfrom()函数,直到我按下Ctrl + C.我已经尝试设置处理程序等(来自相关问题),但它们对我来说都太复杂了,或者它是一个简单的函数只是退出程序作为演示。这是我的问题: 该程序挂起recvfrom,直到它收到一个连接(我的猜测),因此,它永远不会有机会专门等待输入。如何设置一个能够很好地发挥作用的事件?
谢谢!
答案 0 :(得分:1)
在CTRL-C处理程序中,设置一个标志,并在while
循环中将该标志用作条件。
哦,如果你不在POSIX系统上系统调用可能被信号中断,你可能想要使套接字无阻塞并使用例如select
(有一个小超时)来轮询数据。
Windows对这样的方案有几个问题。主要问题是CTRL-C处理程序不能中断函数调用。相反,你必须轮询在循环中是否有任何东西要接收,同时还要检查“退出循环”标志。
可以这样做:
bool ExitRecvLoop = false;
BOOL CtrlHandler(DWORD type)
{
if (type == CTRL_C_EVENT)
{
ExitRecvLoop = true;
return TRUE;
}
return FALSE; // Call next handler
}
// ...
SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
while (!ExitRecvLoop)
{
fd_set rs;
FD_ZERO(&rs);
FD_SET(sd, &rs);
timeval timeout = { 0, 1000 }; // One millisecond
if (select(sd + 1, &rs, NULL, NULL, &timeout) < 0)
{
// Handle error
}
else
{
if (FD_ISSET(sd, &rs))
{
// Data to receive, call `recvfrom`
}
}
}
您可能必须使套接字无阻塞才能生效(请参阅ioctlsocket
函数了解如何)。
答案 1 :(得分:1)
断开recvFrom()循环,以便主线程可以等待用户输入。当用户请求停止时,从主线程关闭fd,recvFrom()将立即返回错误,因此允许recvFrom()线程退出。