服务端给消息里加个时间 客户端里可见本次消息时间和上次消息时间 消息打印结果如图 客户打印出来的第一条消息里lastEventId输出的时间与服务器发送的第一条消息的时间相同,也就是说客户端只打印了服务器发送过来的第二条消息,嗯。。。我有点整不明白了
<?php use Workerman\Worker; use Workerman\Connection\TcpConnection; use Workerman\Protocols\Http\Request; use Workerman\Protocols\Http\ServerSentEvents; use Workerman\Protocols\Http\Response; use Workerman\Timer; require_once __DIR__ . '/vendor/autoload.php'; $worker = new Worker('http://0.0.0.0:8080'); $worker->onMessage = function(TcpConnection $connection, Request $request) { // 如果Accept头是text/event-stream则说明是SSE请求 if ($request->header('accept') === 'text/event-stream') { // 首先发送一个 Content-Type: text/event-stream 头的响应 $connection->send(new Response(200, ['Content-Type' => 'text/event-stream'])); // 定时向客户端推送数据 $timer_id = Timer::add(2, function () use ($connection, &$timer_id){ static $id = 0; // 连接关闭的时候要将定时器删除,避免定时器不断累积导致内存泄漏 if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) { Timer::del($timer_id); return; } // 发送message事件,事件携带的数据为hello,消息id可以不传 $connection->send(new ServerSentEvents(['event' => 'message', 'data' => 'hello', 'id'=>$id++])); }); return; } $connection->send("<script> var source = new EventSource('http://127.0.0.1:8080'); source.addEventListener('message', function (event) { var data = event.data; console.log(event); // 输出 hello }, false); </script>"); }; // 运行worker Worker::runAll();
id从0开始输出的,没问题
这个id对应的是event.lastEventId,但lastEvent客户端并没有收到,比如改成这样比对一下服务端发送的内容和客户端打印出的内容
$timer_id = Timer::add(2, function () use ($connection, &$timer_id){ static $id = 0; // 连接关闭的时候要将定时器删除,避免定时器不断累积导致内存泄漏 if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) { Timer::del($timer_id); return; } // 发送message事件,事件携带的数据为hello,消息id可以不传 $data='data of event with ID '.$id; echo "I'm about send msgid:$id".PHP_EOL; $connection->send(new ServerSentEvents(['event' => 'message', 'data' => $data, 'id'=>$id])); $id++; });
是不是服务端发送的数据,第一次客户端收不到;客户端第二次收到的数据中lastEventId却可以获取到服务端第一次发送的id
嗯嗯 是这样
你看看你的eventsource状态,在第一次发送数据后有没有变化
如果只发送1次就把timer删掉的话,客户端也收不到消息
console.log(event.target.readyState); 输出>>1
看源码,你可以先发送一个ping出去,然后再去send就可以了
这是我改过的[表情],哈哈哈
其实就是这样发个空的消息呗 $connection->send(new Response(200, ['Content-Type' => 'text/event-stream' , 'Access-Control-Allow-Origin' => '*'])); $time=time(); $connection->send(new ServerSentEvents(['data' => '', 'id'=>$time]));
先发一条数据,然后再定时器这样也可以
我发现不是没有第一条消息,而是第一条消息跟着header走了,你看看header, 讨厌没有边界的SSe data
哈哈哈,能用就行
id从0开始输出的,没问题
这个id对应的是event.lastEventId,但lastEvent客户端并没有收到,比如改成这样比对一下服务端发送的内容和客户端打印出的内容
$timer_id = Timer::add(2, function () use ($connection, &$timer_id){
static $id = 0;
// 连接关闭的时候要将定时器删除,避免定时器不断累积导致内存泄漏
if ($connection->getStatus() !== TcpConnection::STATUS_ESTABLISHED) {
Timer::del($timer_id);
return;
}
// 发送message事件,事件携带的数据为hello,消息id可以不传
$data='data of event with ID '.$id;
echo "I'm about send msgid:$id".PHP_EOL;
$connection->send(new ServerSentEvents(['event' => 'message', 'data' => $data, 'id'=>$id]));
$id++;
});
是不是服务端发送的数据,第一次客户端收不到;客户端第二次收到的数据中lastEventId却可以获取到服务端第一次发送的id
嗯嗯
是这样
你看看你的eventsource状态,在第一次发送数据后有没有变化
如果只发送1次就把timer删掉的话,客户端也收不到消息
console.log(event.target.readyState); 输出>>1
看源码,你可以先发送一个ping出去,然后再去send就可以了
这是我改过的[表情],哈哈哈
其实就是这样发个空的消息呗
$connection->send(new Response(200, ['Content-Type' => 'text/event-stream' , 'Access-Control-Allow-Origin' => '*']));
$time=time();
$connection->send(new ServerSentEvents(['data' => '', 'id'=>$time]));
先发一条数据,然后再定时器这样也可以
我发现不是没有第一条消息,而是第一条消息跟着header走了,你看看header, 讨厌没有边界的SSe data
哈哈哈,能用就行