【问题标题】:C++ How to exit out of a while loop recvfrom()C ++如何退出while循环recvfrom()
【发布时间】:2013-08-09 18:38:11
【问题描述】:

我正在尝试创建一个 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;
   }
       }

我希望在按下 Ctrl + C 之前运行这个 recvfrom() 函数。我已经尝试设置处理程序等(来自相关问题),但它们要么对我来说太复杂,要么是一个简单的函数只是作为演示退出程序。这是我的问题: 该程序挂在 recvfrom 上,直到它收到一个连接(我的猜测),所以,它永远没有机会专门等待输入。我怎样才能设置一个可以很好地工作的事件?

谢谢!

【问题讨论】:

  • 我通过stackoverflow.com/questions/17766550/…>找到了解决方案

标签: c++ sockets while-loop


【解决方案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 函数了解如何操作)。

【讨论】:

  • 感谢您的评论,您知道我可以查看的任何示例或文档吗?
  • @Daaksin 在什么系统上? Windows 或 POSIX(例如 Linux 或 OSX)?
  • @MartinJames 如果您有更好、更特定于 Windows 的方法来执行此操作,欢迎您提供自己的答案。 :)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2019-08-03
    • 1970-01-01
    • 2018-03-18
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2014-11-28
    • 1970-01-01
    相关资源
    最近更新 更多