TCP套接字:检测对等方是不是在发送前关闭? (Linux)

Posted

技术标签:

【中文标题】TCP套接字:检测对等方是不是在发送前关闭? (Linux)【英文标题】:TCP socket: detect if peer has shut down before sending? (Linux)TCP套接字:检测对等方是否在发送前关闭? (Linux) 【发布时间】:2012-09-06 11:55:16 【问题描述】:

是否有任何直接命令来检测对等方是否在发送之前关闭/关闭其套接字?

我这样做:

int sendResult = send( mySD, bufferPtr, numberToSend, MSG_NOSIGNAL );

send() 确实很乐意接受该消息并似乎发送它(正返回值),只有 下一次 我尝试发送它时返回错误。这意味着:我收到警告 1 消息太晚了。

是的,我之前使用的是select(),但即使对等方已关闭,它仍然返回 1。

作为一种解决方法,我可以在调用 send() 之前直接使用 recv() 执行 0 字节读取,这会告诉我“连接正常”(-1) 或“对等关闭”(0) 并且几乎没有工作:

int readTest = recv( mySD, NULL, 0, MSG_DONTWAIT | MSG_PEEK );

但是从语义的角度来看,当我真正想要发送时,阅读确实“感觉”不对,我真正想要的只是一个测试时间>。那么是否有诸如“套接字状态”之类的命令,我可以直接找出我需要什么? recv() 内部使用的那种东西?

【问题讨论】:

从语义的角度来看,当您真正想要检查对等方是否已关闭并随后发送时,它确实没有感觉不对。如果您想知道您的对等方是否已关闭,那么您需要找出它,在这种情况下只需调用 read 即可。 显示您对select() 的呼叫。有可能第三组 (exceptfds) 可以用来检测这一点。 int selectRes = select(mySD + 1, NULL, &tempSDSet, NULL, &timeout); @unwind 否。传入的关闭是读取事件,而不是异常事件。 猜猜我得到了全貌:“Peer close”是一个读取事件,因此为 read 调用 select() 会产生“true”,因此我进行了读取(例如与recv()) 并得到“0”,它告诉我发生了什么。感谢大家的贡献和帮助我理解! 【参考方案1】:

由于您的程序是基于选择的,我相信您为读取和写入 fd 集注册了套接字。如果是,您将获得 read fd set 的选择返回,并且您将“recv”最终为“0”并因此关闭套接字。

【讨论】:

我使用不同的选择进行读写。所以你建议做类似select( mySD + 1, &tempSDSet, &tempSDSet, NULL, &timeout ); 的事情?我试试看,谢谢! 如果你有单线程进程,你必须有一个非常充分的理由让两个选择分别用于读取和写入 fds。 应用程序就是这样构建的。通常,它只向服务器发送消息,只有在这里,然后它必须读取前一个请求的答案。所以读和写是分开处理的,如果需要的话,在更高的层次上组合成一个“请求操作”。【参考方案2】:

我想套接字之上的协议确实实现了乒乓机制是有原因的?

最好的,彼得

【讨论】:

这不是答案。有些人可能会对你投反对票,只是说。 从语法上讲你是完全正确的。感谢您的说明,也感谢您不降级。然而,问题可以暗示答案,就像在这种情况下我打算说:“看,说你是否在套接字层上连接被认为是一件不平凡的事情,否则人们不会费心去实现 pings 和 pongs。不可靠。对你来说最简单的方法是包括一个简单的乒乓机制。够公平吗? 我认为有这样的问题。 @ilmiacs:我真的很想在应用程序级别实现请求-应答协议(因此:我发送消息,对等方必须确认每个收据)。但是,要处理的协议已经给定了,而且是固定的,并没有提供这种东西(我发了一个消息,没有得到答复),所以我必须依赖 TCP 机制。这些消息可能每分钟(甚至更长)发生一次,因此向用户发出错误信号(设备上的 LED)应该尽快发生,因此在消息已(未)发送后立即发生,而不是在 next 之后 消息。 好的,相信了。我在这里很新。感谢您的建议。我可以删除我的“答案”吗?

以上是关于TCP套接字:检测对等方是不是在发送前关闭? (Linux)的主要内容,如果未能解决你的问题,请参考以下文章

在 TCP 中检测到其他对等方已关闭

libevent 如何检测到套接字已关闭

“对等方重置连接”是啥意思?

UDP/TCP 流程与总结

浏览器上的 GCDAsyncSocket 立即连接和断开连接,并出现“远程对等方关闭套接字”错误

在 webrtc 视频聊天中检测到对等方的浏览器已关闭