我有一个小服务器(用PHP编写),监听使用socket_create
创建的套接字并使用socket_accept
接受连接。使用socket_select
扫描所有连接,并且每当该调用返回时,服务器接受来自套接字的新连接读取。当客户端断开连接时,socket_select
返回与之关联的套接字,然后服务器可以通过检查socket_read
返回空字符串来检测断开连接。
到目前为止,所有这些都是"通过这本书"并且运行良好,但问题是如果客户端断开连接(例如,如果它崩溃),那么它的套接字进入socket_select
返回的列表(如预期的那样),但是当服务器调用{ {1}},它会触发错误:
socket_read
显然,在调用socket_read(): unable to read from socket
之前,我必须在套接字上添加一些检查,但我无法找到它会是什么。检查该套接字的方法是什么?请参阅代码中的注释。
socket_read
答案 0 :(得分:0)
您没有检查select的结果,必须这样做才能知道是否有可供阅读的套接字。
$r = socket_select($readable_sockets, $null, $null, 0);
if ($r === false) {
/* socket_select Error handling */
} else if ($r > 0) {
/* At least at one of the sockets something interesting happened */
}
select函数将更改$readable_sockets
数组以防有待读取的内容,或者在超时的情况下可能未定义或未触及。
注意:请注意,需要非常小心地处理某些套接字实现。
一些基本规则:
您应该始终尝试使用socket_select()
而不会超时。您
如果没有可用数据,程序应该无所事事。码
取决于超时的通常不是便携式的,也很难
调试。
如果不是,则不得将任何套接字资源添加到任何集合中
打算在socket_select()
电话后检查其结果,并且
适当回应。在socket_select()
返回后,所有套接字
必须检查所有数组中的资源。任何套接字资源
必须写入可写的,以及任何套接字资源
必须阅读。
如果您读取/写入套接字,请注意数组中的返回值 他们不一定要读/写全部数据 您已请求。准备好甚至只能读/写 一个字节。
根据我的经验select
没有办法知道套接字何时崩溃,直到你尝试从中读取它时,永远不会将崩溃的套接字作为候选进行读取,除非在正常关闭或关闭时完成另一端。你可以做的一件事是每个套接字都有一个超时,如果套接字没有活动,比方说30分钟,那么你可以丢弃它。
我还将用户的套接字与主套接字分开。对用户的套接字执行选择并分派其数据,然后对主套接字执行选择并接受新连接。但这取决于你,如果你想在每次迭代中检查主套接字,那就没关系。