【发布时间】:2014-01-03 23:23:21
【问题描述】:
我已经成功实现了下一个方案:一个 php 套接字服务器脚本,它向所有连接的客户端脚本广播消息,并且这些客户端脚本由前端脚本上的事件源监听。所以,基本上,方案是:server.php -> client.php -> front.php。
但我一直在努力解决client.php 的这部分问题:
while(TRUE)
{
$read = array();
$read[] = $client_socket;
if( socket_select($read, $write, $except, 10) === FALSE ){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
file_put_contents("select_result.log", "Could not listen on socket : [$errorcode] $errormsg".PHP_EOL);
}
if( !($client_message = @socket_read($client_socket, 1024)) ){
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
file_put_contents("read_result.log", "Couldn't read socket: [$errorcode] $errormsg".PHP_EOL, FILE_APPEND);
}
if($client_message == FALSE) {
$client_message = "event: keep_alive" . PHP_EOL
. "data: keep_alive" . PHP_EOL . PHP_EOL;
}
echo $client_message;
if( ob_get_level() > 0 ) ob_flush();
flush();
}
当在浏览器中打开 front.php 脚本(使用 event-source)时,它可以正常工作,但是当我关闭或重新加载时,它也会以某种方式检测到断开连接front.php 在浏览器窗口中。以下是来自server.php 的检测断开连接的部分:
if( !($client_input = @socket_read($client, 1024))) {
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
echo "$errorcode".PHP_EOL;
}
if ( $client_input === FALSE ) {
$socket_key = array_search($client, $client_sockets);
socket_getpeername($client, $client_address, $client_port);
socket_close($client);//?!!!
unset($client_sockets[$socket_key]);
echo "[$client_address : $client_port disconnected]".PHP_EOL;
}
如您所见,当无法从客户端读取数据时会发生这种情况。从理论上讲,当我关闭front.php 时,client.php 应该仍然在后台无限循环中工作,因为我没有任何循环中断,但是 - 惊喜! - 它停止。实验上,我发现这是由于ob_flush() 函数而发生的。当它被评论时,server.php 不会检测到断开连接(浏览器窗口关闭/重新加载)。怎么会这样?根据手册,ob_flush() 不返回任何值。也没有检测到错误...我不知道该怎么想,也找不到为什么会发生这种情况。请帮忙。
【问题讨论】:
-
是“front.php”HTML 页面,包含 JavaScript 等。即出于这个问题的目的,它真的可以称为“front.html”吗? (或者,你的 HTML 客户端使用 EventSource 连接到的 front.php 是什么?)。换句话说,在你的浏览器运行的 JavaScript 中,你是
new EventSource("client.php")还是new EventSource("front.php")? -
你是对的,是的,它可以很容易地称为
front.html,而我是new EventSource("client.php");client.php然后打开到server.php的套接字连接。
标签: php sockets server-sent-events