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

Kac*_*acy 2 php sockets

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

我已经看到一些代码示例使用php的socket_select()方法中的读取数组来检测客户端套接字断开连接,例如: 如何在PHP套接字侦听器上检测客户端断开连接?

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

hek*_*mgl 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()就会意识到这一点.

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

不幸的是,我没有TCP keep-alives其他操作系统的经验,但我想也支持这样的东西.