PHP版本:Debian 3.2.54-2 x86_64上的5.4.4。我正在使用流套接字。 我创建了简单的服务器和客户端应用程序来说明我的问题:
<?php
$client = false;
$server_sock = stream_socket_server("tcp://127.0.0.1:20015", $errNo, $errorMessage);
if ($server_sock == false) die("Could not bind to socket: {$errNo} - {$errorMessage}");
while (true) {
if ($client !== false) {
if (feof($client)) $data = false;
else $data = stream_get_contents($client);
if ($data === false) {
fclose($client);
$client = false;
echo "Client disconnected\n";
continue;
} else if ($data === "") continue;
echo "Received: " . $data . "\n";
} else {
$clients = array($server_sock);
$num_streams = stream_select($clients, $write = null, $except = null, 0, 200000);
if ($num_streams > 0) {
if (in_array($server_sock, $clients)) {
$client = stream_socket_accept($server_sock);
if ($client) {
if(!stream_set_blocking($client, 0)) echo "stream_set_blocking() error\n";
} else {
echo "stream_socket_accept() error\n";
$client = false;
}
}
}
}
}
?>
客户代码:
<?php
$client = stream_socket_client("tcp://127.0.0.1:20015", $errNo, $errorMessage);
if ($client == false) die("Could not connect to server: {$errNo} - {$errorMessage}\n");
if(!stream_set_blocking($client, 0)) echo "stream_set_blocking() error\n";
$tick = true;
while (true) {
sleep(2);
if ($tick) $toSend = "TICK "; else $toSend = "TOCK ";
$tick = !$tick;
$toSend .= time();
$num_bytes = fwrite($client, $toSend);
if ($num_bytes === false || $num_bytes < strlen($toSend)) { echo "fwrite() error\n"; continue; }
else echo "Data sent: {$toSend}. Bytes: {$num_bytes}\n";
}
if (fclose($client)) echo "Socket closed\n";
else echo "fclose() error\n";
?>
问题:如果我手动关闭服务器(模拟丢失的连接),在服务器关闭后首先调用fwrite()(在客户端),不会抛出任何错误。第二次调用fwrite()返回0并生成PHP通知“PHP注意:fwrite():发送15个字节失败,错误的是errno = 32 Broken pipe”正如预期的那样。使用第一个fwrite()调用发送的所有内容都将丢失,但客户端“认为”一切正常。在生产环境中,错误客户端将尝试重新连接,如果成功,它将尝试重新发送数据。但是客户并不完全了解情况。为什么fwrite()表现得像这样?我试图在流上启用阻塞模式,使用超时,fwrite(),然后获取流元数据,但似乎fwrite()永远不会超时,即使它给出了错误。任何提示或解决方案?