【问题标题】:breaking out from socket select从套接字选择中脱颖而出
【发布时间】:2011-01-30 00:18:36
【问题描述】:

我有一个循环,基本上每隔几秒调用一次(超时后):

 while(true){

    if(finished)
       return;

    switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)){
        case SOCKET_ERROR : report bad stuff etc; return;
        default : break;
    }

    // do stuff with the incoming connection
 }

所以基本上每隔几秒钟(由 tv 指定),它就会重新激活监听。

这是在线程 B(不是主线程)上运行的。有时我想立即从线程 A(主线程)结束此接受器循环,但似乎我必须等到时间间隔结束..

有没有办法从另一个线程中断 select 函数,以便线程 B 可以立即退出?

【问题讨论】:

  • 旁注:你可以剪掉 if 语句,只写 while(!finished)。
  • 这将占用 100% 的 CPU 时间。绝对不能接受。
  • 哎呀,我一定是看错了
  • Write on Windows :) 您有几个选项可以异步执行套接字 I/O。例如,您可以将套接字与可等待事件 (WSAEventSelect) 相关联,然后等待这些事件,也可以选择您的自定义事件,以及您需要的超时时间

标签: c++ c sockets


【解决方案1】:

是的,您创建了一对连接的套接字。然后线程 B 写入套接字的一侧,线程 A 添加另一侧套接字以进行选择。所以一旦B写入socket A退出select,不要忘记从socket中读取这个字节。

这是中断选择的最标准和最常见的方式。

注意事项:

在 Unix 下,使用 socketpair 创建一对套接字,在 windows 下有点棘手,但在 Windows 上搜索 socketpair 会得到代码示例。

【讨论】:

  • 啊,我刚刚使用了 pipe(2),它似乎可以工作。我最终可能不得不担心它的窗口对应物..
【解决方案2】:

你不能让超时时间足够短吗(比如 10 毫秒左右?)。

这些“只是创建一个虚拟连接”类型的解决方案似乎有点被黑了。我个人认为,如果一个应用程序设计得很好,并发任务永远不必被强制中断,只要有工作人员检查就足够了(这也是 boost.threads 没有终止功能的原因)。

编辑制作了这个答案的简历。这很糟糕,但它可能有助于其他人理解它为什么不好,这在​​ cmets 中有解释。

【讨论】:

  • -1 这是一个非常糟糕的解决方案,它只会消耗 CPU 并且仍然存在延迟问题。对此有标准解决方案。
  • CPU 成本如何?与创建虚拟套接字连接相比,等待 CPU 的 10 毫秒是多少?
  • CPU 开销在于减少超时,使循环运行更频繁。
  • “dummy”连接的优点是写入的字节可以有意义,这样线程就不再需要共享状态(大概finished标志是由另一个线程,需要一些这里似乎缺少的同步)。仅通过消息传递在线程之间进行通信不是“黑客”。有一定的设置,但它可以显着简化应用程序状态模型。我不相信强迫一切快速轮询,而不是使用异步操作来充分利用,完全没有黑客攻击。
  • 即使在设计良好的应用程序中,一个线程也可能会告诉另一个线程停止。这不是强制但非常干净,因为应该停止的线程可以进行清理等等。像“KillThread”这样的东西是一种强有力的方式......
【解决方案3】:

最简单的方法大概是使用pipe(2)创建一个管道,并将读取端添加到readfds。当其他线程想要中断select()时,只需向它写入一个字节,然后再消费它。

【讨论】:

  • 它是一个监听器套接字(一个接受连接的)。这仍然有效吗?我正在考虑调用一些破坏套接字的函数..看看会发生什么。这会安全吗?
  • 它正在等待 a 文件。它不在乎哪个,它只想要某物
  • 它奏效了,我用 unix 管道学到了一两件事!谢谢!顺便说一句,中断后我所做的就是退出程序。所以我不介意消费。没关系吧?
  • 应该是。拆除管道应该会破坏其中的任何东西。
【解决方案4】:

您可以使用来自主线程的 shutdown(Sock, SHUT_RDWR) 调用来退出等待选择调用,这也会在超时之前退出您的另一个线程,因此您无需等到超时到期。

干杯。 :)

【讨论】:

  • 很遗憾,您不能 shutdown 监听套接字。当另一个线程正在或可能正在使用它时,没有安全的方法可以close它。
  • 如果您有下面提到的套接字线程函数,并且如果您从主线程发送shutdown(sock, SHUT_RD),它将唤醒等待其他线程中执行的SockThreadFunction 的选择调用。我已经尝试过了,它工作正常。 SockThreadFunction(){ while(SocketOpen) { //等待选择调用 int Ready = select(pSocket->m_Sock+1, &SockSet, 0, 0, 0); }
  • 他有一个监听套接字。你不能shutdown 监听套接字。它适用于连接的套接字,但它不适用于监听套接字,这是他所拥有的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多