我已经成功实现了下面的方案:一个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
脚本时,它可以正常工作。但是,当我关闭或重新加载浏览器窗口中的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()
不返回任何值。也没有发现任何错误...... 我不知道该怎么想,也找不出这是为什么。请帮帮我。
new EventSource("client.php")
还是new EventSource("front.php")
? - Darren Cookfront.html
,然后我使用new EventSource("client.php")
;client.php
然后打开到server.php
的套接字连接。 - Damaged Organic