我有一个php服务器正在监听1个c#客户端。
建立连接后,它会保持活动状态,直到客户端发送命令“quit”,从而杀死PHP服务器。
但是当c#客户端在没有“quit”命令的情况下断开连接时(即:单击windows窗体中的close(x)按钮),服务器就会继续监听,并且无法从该客户端接收任何其他连接。
有没有办法从服务器端(PHP)检查连接是否仍然存在于客户端。
我的php服务器代码基于:http://php.net/manual/en/sockets.examples.php
的例子1如果有人有兴趣重现错误/错误行为,请粘贴exemple1:http://php.net/manual/en/sockets.examples.php中的代码,通过telnet从局域网中的远程客户端连接,拔掉客户端线... php服务器将永远挂起,不接受新连接
(抱歉我的英语不好)
答案 0 :(得分:2)
在循环中,您需要检查socket_read()
的返回值。如果它返回FALSE,则出现读取错误(可能是由远程主机关闭连接引起的)。您提供的链接中的示例代码涵盖了这种情况。
如果您需要优雅地处理某些错误状态,您可以随时使用socket_last_error()
检查套接字错误代码 - this note描述可能的代码。
修改强>
当使用putty for telnet时,如果我用X按钮关闭,在PHP中正确关闭了connecion,但如果我拔掉了putty机器的以太网线,那么PHP服务器就会挂掉。
杀死PuTTY时关闭连接的原因是PuTTY在退出时关闭其打开的连接。这会导致socket_read()
返回错误代码(我相信ECONNRESET
)。如果你拉网线,它没有机会这样做。
根据网络的配置方式,TCP连接应最终失败。您可以尝试使用SO_RCVTIMEO
设置socket_set_option()
来控制超时,但这并不总是适用于所有平台(我正在看着你,WinSock)。< / p>
或者,您可以使用socket_select()
以合理的超时滚动自己的轮询循环。如果在超时后没有任何连接的套接字有数据要发送,则终止服务器。
答案 1 :(得分:0)
以下代码将显示连接状态。
$address='example.com';
$port = '9065';
if (isset($port) && ($socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP))
&& (socket_connect($socket, $address, $port))) {
$text='Connection successful on IP $address, port $port';
socket_close($socket);
}
else {
$text='Unable to connect<pre>'.socket_strerror(socket_last_error()).'</pre>';
}
echo $text;
答案 2 :(得分:0)
我通过检查socket_select()
$read
数组是否包含相关连接但socket_read()
数据为空(两次)来完成此操作。
似乎socket_select()
将断开连接的客户端添加到$read
数组,而socket_read()
在尝试读取断开连接的客户端数据时会提供空字符串''
。
答案 3 :(得分:0)
正如 Michael Dodd 所说,使用 socket_select() 可以拥有所有已接收数据的套接字以及它们已关闭的套接字。您也可以拥有所有缓冲区可以接受数据进行传输的内容,和/或引发某些异常的内容。确实有这个信息,套接字数组的(单独的)副本必须放在函数的第二个和 / 3d 参数中。 (如果不需要,这个函数必须有 $null 作为一个等于 null 的变量,而不仅仅是 null)
以下示例展示了如何读取数据并测试套接字是否仍处于打开状态。我将此代码用于由 socket_accept() 在侦听套接字上创建的套接字,并且它可以正常工作。可以使用 socket_read 代替 socket_recv。
//all sockets created have been inserted to an array $socketArray
//get a copy of the sockets array
$tempArray = $socketArray;
//this command will remove from $tempArray all sockets that have no data and are alive, with a timeout of 0 sec, 100 msec
socket_select($tempArray, $null, $null, 0, 100);
if (count($tempArray)) {
//if we have some sockets in the array
foreach($tempArray as $socket) {
//read some data
$count = socket_recv($socket, $socketData, 1024, 0);
if ($count) {
//your code to do what you want with $socketData
} else {
//find socket position in initial socket array
$index = array_search($socket, $socketArray);
//if found, remove it from array and close the socket
if ($index !== false) {
array_splice($socketArray, $index, 1);
socket_close($socket);
}
}
}
}