php的socket_select()是否保证检测所有客户端套接字断开连接?

时间:2015-02-20 14:12:31

标签: php sockets

php' socket_select()方法是否可以保证检测所有客户端套接字断开连接?

我已经看到一些代码示例在php的socket_select()方法中使用read数组来检测客户端套接字断开连接,例如: How to detect client disconnection on PHP socket listener?

但是对于所有客户端套接字断开,它是否返回FALSE?如果有任何例外,它们是什么?

1 个答案:

答案 0 :(得分:6)

<强> TL; TR

您需要定期发送包含零长度数据的TCP pakets,并等待来自客户端的ACK以确保它没有物理断开连接。否则socket_select()将假定如果客户端物理断开连接仍然打开连接。在Linux上,内核可以提供帮助 - 它被称为TCP keep-alives


<强>解释

问题是您对ALL类型的客户端断开连接意味着什么?在评论中,您表示您担心不合适的客户端断开连接。如果在客户端发生停电会怎么样?

首先是关于优雅客户端断开连接的简短句子。在TCP中,客户端可以通过两种方式关闭连接:向服务器发送FIN数据包或发送RST数据包。 (后者不太可能发生在客户端)。 socket_select()了解这两种方式如何优雅地实现脱节。

如果客户端在连接打开时物理断开连接,则无法再发送FINRST数据包。出现这种情况可能是因为停电,缺陷电缆,缺陷开关等原因很多......

在这种情况下,连接将永远保持在服务器端打开,因为TCP没有实现超时,这意味着它不需要发送数据包。成功连接后,除非收到FINRST数据包,否则连接将保持打开状态。

所以如何检测断开的连接是不可能的?不,还有办法如何检测这些。该概念称为TCP keep-alive数据包。

TCP keep-alives基于TCP协议的一项功能:当您在TCP中发送数据时,接收方会以ACK数据包响应,表示收到的数据包成功。 TCP keep-alive数据包是包含零长度数据的数据包,只是为了在客户端上触发ACK数据包。请注意,客户端不需要实现keep-alives。它很简单TCP

在Linux上,内核可以帮助发送keep-alives。如果在给定(可配置)超时内没有在套接字上收到数据,则内核将发送这些零长度数据包并在没有收到ACK且具有可配置的时间量时关闭套接字。还有一个可配置的重试间隔。如果内核关闭了套接字,socket_select()就会知道它。

了解如何在Linux上配置TCP keep-aliveshttp://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html

不幸的是,我没有在其他操作系统上使用TCP keep-alives的经验,但我想也支持类似的东西。