【问题标题】:Stopping a blocking receive without closing the socket停止阻塞接收而不关闭套接字
【发布时间】:2017-05-05 09:05:09
【问题描述】:

我面临一个与套接字和多线程相关的设计问题。

让下面的事情:

  • 一组网络协议,其底层是使用 TCP/IP 的套接字层。

  • 一个“发件人”线程:

    • 执行连接过程(包括发送和接收数据)

    • 一旦建立连接,启动一个“接收者”线程在后台接收数据。

    • 发送数据。

    • 当应用程序决定退出时,停止接收线程。

    • 执行断开连接(还涉及发送和接收数据)。

  • 在数据交换阶段(即连接和断开之间)接收数据的“接收者”线程。

我的问题是,当发送者线程想要执行断开连接的过程时,它首先需要停止接收者线程。因为接收线程正在执行阻塞接收,所以我知道停止它的唯一方法是粗暴地关闭套接字。但是这样做会阻止我执行干净的断开连接,因为断开连接过程需要在关闭套接字之前发送和接收数据。

所以我的问题是:是否可以在不关闭套接字的情况下停止阻塞接收,如果可以,我该怎么做?还是我需要重新设计我的应用程序?

我可以在我的阻塞接收中添加一个超时,以便定期检查是否停止接收,但它会感觉不是很响应并且似乎是一种肮脏的方法。

我不会用完整的代码来打扰您,因为它可以按预期工作并且具有依赖性。我的接收是使用 select() 然后是 recv() 执行的,如下所示:

iRes = select( 0, & fdRead, NULL, NULL, m_nTmout == 0 ? NULL : & tv );
...
iRes = recv( m_hSock, (char *) pBytes, nMaxLen, 0 );

这是 Win32 代码,但我在 Linux 上也有类似的代码(更具体地说是 Android)。在这两种情况下,我都使用 C 和 C++。

谢谢。

【问题讨论】:

  • 对接收线程的读取设置超时只会影响退出点的响应能力 - 它在正常运行期间应该可以忽略不计(尽管使用的 CPU 成本很小,因为线程不会不读取时完全被屏蔽)
  • 没错,但必须有更清洁的方法,对吧?
  • 我不确定是否有,实际上,至少不是便携的。我知道的唯一方法是向每个子线程发送一个信号,以便正在进行的读取被 EINTR 错误代码杀死(在 POSIX 系统上)
  • 好的,感谢您的帮助。不幸的是,我不仅仅针对 POSIX 系统,所以我应该使用超时方法。
  • 如果断线过程涉及发送和接收数据(在应用层),接收线程能否识别(通过查看接收到的数据)发起断线,需要停止

标签: c multithreading sockets


【解决方案1】:

当您使用select() 作为阻塞操作时,您可以创建pipe() 用于将命令从发送者 传递到接收者。

通过将该管道的读取端添加到select() 读取列表,您可以确定写入该管道的任何命令都会唤醒select() 调用。所以接收者将能够处理这个命令。

【讨论】:

  • 感谢您的帮助。我会研究一下,看看是否可以在我所针对的所有平台上完成。
猜你喜欢
  • 1970-01-01
  • 2010-12-30
  • 2017-01-11
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 2014-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多