C++如何退出while循环recvfrom()

C++ How to exit out of a while loop recvfrom()

本文关键字:while 循环 recvfrom 何退出 C++ 退出      更新时间:2023-10-16

我正试图创建一个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上,直到它接收到连接(我猜),所以,它从来没有机会专门等待输入。我该如何设置一个能很好地实现这一点的活动?

谢谢!

在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函数了解如何操作)。

线程关闭recvFrom()循环,以便主线程可以等待用户输入。当用户请求停止时,从主线程关闭fd,recvFrom()将立即返回并返回一个错误,因此允许您的recv弗洛()线程退出。