检测非阻塞套接字上的关闭连接

Posted

技术标签:

【中文标题】检测非阻塞套接字上的关闭连接【英文标题】:Detect closed connection on non blocking socket 【发布时间】:2015-07-20 05:51:02 【问题描述】:

如果我的问题重复,我真的很抱歉,但我没有在网站上找到有用的信息。

我正在使用非阻塞套接字和 select()。如何检测客户端是否关闭了非阻塞套接字上的连接?我看到当没有数据可供读取以及连接关闭时,read() 返回 -1 和 errno = EWOULDBLOCK。

如何区分上述情况?

【问题讨论】:

【参考方案1】:

当对端关闭连接时:

    select() 将返回可读的套接字。 套接字上的recv()read() 将返回零。

当没有数据可供读取时,我看到 read() 返回 -1 且 errno = EWOULDBLOCK

正确,但连接没有关闭。

以及连接关闭时。

不,你没有。这是不正确的。它返回零。

如何区分上述情况?

它们不一样,它们的表现方式也不相同。

【讨论】:

你是对的!我刚刚制作了一个玩具客户端 - 服务器应用程序,它按照你和我的解释工作。在我的原始应用程序中,我从浏览器收集连接,并且我看到创建了一个线程来从服务器获取每个图像。线程获取图像时是否有可能不关闭套接字/连接? 是的,这就是 HTTP keep-alive 的效果。但是,如果您正在发送,则无需担心接收时会发生什么。发送图片后关闭套接字即可。 不,我的应用程序位于服务器端和客户端之间。它就像一个转发器,也就是说,它必须收集从一侧到达的数据,然后将它们转发到另一侧。我的转发器应用程序应该能够检测到客户端何时关闭连接,因为我需要关闭无用的套接字和无用的线程(我的意思是,完成工作的线程)。那么,如果我使用 HTTP keep-alive,有没有办法检测到线程工作的结束? 解决方案:在长连接中,经过一定时间后,read()返回0,所以可以检测到关闭的连接。 @LucaForte '经过一段时间' 与它无关。当对等方关闭连接时,read() 返回零,这可能是在一秒钟、一年或一个世纪之后。【参考方案2】:

当对等端关闭特定套接字的连接时,在此套接字上调用read() 将返回0。此行为与套接字的阻塞状态无关。

来自man 2 read(我的斜体):

返回值

成功时,返回读取的字节数(零表示文件结束

【讨论】:

Any 调用返回零。如果第一次调用返回零,则表明对等端关闭而不发送任何内容的非常不寻常的情况。一旦返回零,它将继续返回。 删除了三振。没有人关心之前的错误,如果他们这样做了,它们就会出现在编辑历史记录中。 @EJP:谢谢,我只是把它留在里面以避免悬空的评论。 :-) 所以让我们清理 cmets ...

以上是关于检测非阻塞套接字上的关闭连接的主要内容,如果未能解决你的问题,请参考以下文章

Socket编程中,阻塞与非阻塞的区别

DLL 中的非阻塞套接字(无窗口)

在linux中连接非阻塞套接字的正确方法是啥

了解非阻塞套接字上的 EWOULDBLOCK

在 C 中使用非阻塞套接字连接

windows下在非阻塞TCP套接字上使用SO_SNDBUF的奇怪行为