我试图在PHP后端使用SSE向用户发送消息。
后端代码的功能部分看起来像 -
<?php
set_time_limit(0);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
ignore_user_abort(0);
@session_start();
ob_start();
echo "retry: 1000\n";
ob_flush();
flush();
require_once 'sql_connection_class.php';
require 'chatbox_class.php';
$chatbox=new chatboxclass($_GET['friendid']);
function recursivesenddata(){
global $chatbox;
$jsonobj=$chatbox->jsonloadunreadmessages();
//append json object
if($jsonobj!=-1){
> echo "data:{$jsonobj}\n\n";
> ob_flush();
> flush();
> }else{
> //don't send anything
> }
}
while(true){
recursivesenddata();
session_write_close();
sleep(1);
}
?>
&#13;
当用户关闭页面时,似乎ignore_user_abort(0)没有做任何事情。
在$ chatbox-&gt; jsonloadunreadmessages()中,有一个函数只能在页面打开时执行,它会更新mySQL数据库中的内容。但是即使页面关闭,这个脚本仍然在服务器上运行!
无论如何,当用户关闭页面以退出无限循环时,是否还要检查服务器端?答案 0 :(得分:1)
连接套接字关闭后,应立即终止PHP脚本。如果脚本在用户关闭页面时继续运行,那么Apache / PHP配置就会出现问题。
当客户端明确调用EventSource.close()
,由于网络问题导致连接丢失,客户端关闭页面或PHP脚本终止时,可能会发生套接字关闭。
ignore_user_abort(false)
什么都不做;这是默认行为(脚本在连接关闭时终止)。将true
作为参数传递将使您的脚本在连接中继续存在,但这不会解决您的问题。
您的retry: 1000
没有任何意义,因为您永远不会关闭套接字服务器端。
当客户端激活EventSource
对象并且仅在客户端请求时终止(或者如果网络出现故障)时,应该调用PHP脚本,因此每个聊天连接只需要进行一次初始数据库调整。假设客户端没有做任何会关闭连接的事情。
顺便说一下,这会给服务器带来很大压力:每个聊天客户端都会有一个PHP进程在整个聊天时间内运行,并且轮询周期大约是10倍(10秒就足够了)。每隔30秒左右让客户轮询新邮件就不那么浪费了。
答案 1 :(得分:0)
在IIS系统上忽略ignore_user_abort(),您的配置可能会阻止它。
尝试在while循环中使用connection_aborted():
while ( connection_aborted() == 0 ) {
recursivesenddata();
session_write_close();
sleep(1);
}