【问题标题】:How to exit a blocking recv() call? [duplicate]如何退出阻塞的 recv() 调用? [复制]
【发布时间】:2015-03-10 06:18:18
【问题描述】:

基于这个question,当你在recv()已经在使用的socket上调用closesocket()时,一个RST数据包将被发送到另一端,而不是执行一个优雅的断开连接(4路握手)。

但我希望执行优雅的断开连接,所以我需要在调用closesocket() 之前退出recv()。

有没有办法做到这一点?

【问题讨论】:

  • 您不能在recv 已经在使用的套接字上调用closesocket。尝试编写代码来做到这一点,这几乎是不可能的。您需要某种方式来知道recv 已经使用某种线程上下文检查访问了套接字。您的代码将不可避免地存在可能发生可怕事情的竞争条件。
  • "当您在 recv() 已经使用的套接字上调用 closesocket() 时,将向另一端发送一个 RST 数据包" 这确实不是真的。 RST 是由于在有未读待处理数据时关闭套接字的行为引起的。

标签: c++ sockets winapi network-programming winsock


【解决方案1】:

您可以shutdown() 套接字进行输入。 recv() 将解锁并返回零,每个人都会很高兴。

【讨论】:

  • 这并不总是有效的,就像stackoverflow.com/questions/29737707/exit-a-blocking-recv-call 使用正确的服务器(不接受输入)一样。这和 David Schwartz 的评论(“Winsock 客户端绝不能在 s 上与另一个 Winsock 函数调用同时发出 closesocket。”的更深层次的变体。)让我觉得关闭不起作用时唯一的解决方案是......非阻塞套接字。
  • 如果在连接后拔下路由器的电缆,它也不起作用,有效地切断了通信,但对 TCP/IP 连接没有立即影响 (stackoverflow.com/questions/13085676/…)。
  • @Liviu 这个答案中没有关于调用closesocket() 的内容,并且您引用的链接中也没有任何内容可以确认您的说法,即当电缆连接时关闭套接字以进行输入不起作用拉。实际上很难看出这两个事件之间有任何联系。
  • 伙计,一年后我无法验证您的说法(不同的工作,没有路由器)...但是,如果(真实网络)连接断开(通过拉动未直接连接到计算机的电缆),您的 shutdown 不会解除任何阻塞,因为阻塞套接字不知道连接已关闭,它会等待一些超时(可能长达几分钟:对我们来说可能是 2 分钟)
  • 我现在明白了……您是解决合法问题的“专家”:[“退出阻塞的 recv() 调用”] (stackoverflow.com/questions/29737707/exit-a-blocking-recv-call)。在说“对其他人有效”之前,您是否甚至费心对其进行测试? (这个网站确实有问题,比如允许你关闭问题。)
【解决方案2】:

这里真正的问题是,一个确定的终止线程,terminatethread(),有各种关于它使用的不良影响的警告。我一直在使用这种方法来退出recv()。 windows 文档说“在应用 terminatethread 之前,你必须知道线程在做什么”,好吧,我们知道它在做什么,它在 recv() 中。问题不在于 THREAD 在做什么,而在于 Windows 内核在做什么。

在嵌入式系统实时操作系统中,我已经完成了 killthread() 是可行的。这并不容易,您必须找到线程拥有的每一个锁和资源并将其退出。只有操作系统拥有这种信息(和权力)。

【讨论】:

  • terminatethread() 未在问题中提及。很难理解为什么这个“真正的问题”是相关的。
  • terminatethread 可以用作最后的手段(当上一个答案,接受的“解决方案”不起作用时)停止阻塞套接字的线程。
  • 问题是(你读了吗?)如何退出阻塞的 recv() 调用?终止调用线程是一种方法。
猜你喜欢
  • 2015-06-26
  • 2016-12-20
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2016-12-29
相关资源
最近更新 更多