什么是 Server-Sent Events?
Server-Sent Events(SSE)是一种基于 HTTP 的服务器推送技术,它允许服务器实时向客户端发送事件流。SSE 是一种轻量级的实时通信协议,它比 WebSocket 更容易实现和维护,因为它使用了标准的 HTTP 协议,而不需要额外的握手和协议。
SSE 的工作原理很简单:客户端通过一个 HTTP 请求连接到服务器,服务器返回一个 MIME 类型为 text/event-stream
的响应。客户端通过这个连接接收服务器发送的事件流,而服务器可以随时向客户端发送事件。这个事件流可以包含任意的数据,例如 JSON、XML、HTML 等。
在 Laravel 应用中使用 SSE
在 Laravel 应用中使用 SSE 非常简单,因为 Laravel 已经提供了一个 SSE 的实现。我们可以使用 Symfony\Component\HttpFoundation\StreamedResponse
类来实现 SSE。
首先,我们需要安装 symfony/http-foundation
包:
composer require symfony/http-foundation
然后,我们可以创建一个 SSE 路由:
// javascriptcn.com 代码示例 use Symfony\Component\HttpFoundation\StreamedResponse; Route::get('/sse', function () { $response = new StreamedResponse(function () { while (true) { $data = [ 'time' => time(), ]; echo "data: " . json_encode($data) . "\n\n"; ob_flush(); flush(); sleep(1); } }); $response->headers->set('Content-Type', 'text/event-stream'); $response->headers->set('Cache-Control', 'no-cache'); return $response; });
这个路由创建了一个 SSE 连接,它每秒钟向客户端发送一个包含当前时间的事件。我们使用 Symfony\Component\HttpFoundation\StreamedResponse
类来实现 SSE,它的构造函数接受一个回调函数,这个回调函数会在每次请求时被调用。
在回调函数中,我们使用 echo
和 ob_flush()
和 flush()
函数来向客户端发送数据。我们使用 echo
函数来输出事件数据,ob_flush()
和 flush()
函数用来刷新输出缓冲区,以确保数据被立即发送到客户端。
我们还设置了响应的头部,将 Content-Type 设置为 text/event-stream
,这样浏览器就知道这是一个 SSE 连接。我们还将 Cache-Control 设置为 no-cache
,这样浏览器就不会缓存这个响应。
现在,我们可以在浏览器中访问 /sse
路由,并打开浏览器的开发者工具,查看控制台。你应该能看到每秒钟输出一个包含当前时间的事件。
使用 SSE 实现实时通信
SSE 可以用来实现实时通信,例如聊天应用、实时通知等。在这个例子中,我们可以使用 SSE 来实现一个简单的聊天应用。
首先,我们需要创建一个 SSE 路由,它接受客户端发送的消息,并将消息发送给所有连接到 SSE 的客户端:
// javascriptcn.com 代码示例 use Symfony\Component\HttpFoundation\StreamedResponse; Route::get('/chat', function () { $connections = []; $response = new StreamedResponse(function () use (&$connections) { while (true) { $data = [ 'time' => time(), ]; foreach ($connections as $connection) { echo "data: " . json_encode($data) . "\n\n"; ob_flush(); flush(); } sleep(1); } }); $response->headers->set('Content-Type', 'text/event-stream'); $response->headers->set('Cache-Control', 'no-cache'); $response->send(); return $response; }); Route::post('/chat', function () { $message = request()->input('message'); $data = [ 'type' => 'message', 'message' => $message, ]; broadcast($data); return response()->json([ 'success' => true, ]); }); function broadcast($data) { $redis = app('redis'); $redis->publish('chat', json_encode($data)); }
这个路由创建了一个 SSE 连接,并使用 Redis 的发布订阅机制将客户端发送的消息广播给所有连接到 SSE 的客户端。我们使用 ob_flush()
和 flush()
函数在循环中刷新输出缓冲区,以确保数据被立即发送到客户端。
我们还创建了一个 /chat
的 POST 路由,它接受客户端发送的消息,并将消息广播给所有连接到 SSE 的客户端。我们使用 Redis 的 publish
方法将消息发布到 chat
频道,所有订阅了这个频道的客户端都会收到这个消息。
现在,我们可以在浏览器中打开两个窗口,分别打开 /chat
路由,并在其中一个窗口中输入消息,另一个窗口就会收到这个消息。
总结
本文介绍了如何在 Laravel 应用中使用 Server-Sent Events 实现实时通信。我们使用 Symfony\Component\HttpFoundation\StreamedResponse
类来实现 SSE,创建了一个简单的聊天应用,并使用 Redis 的发布订阅机制将消息广播给所有连接到 SSE 的客户端。SSE 是一种轻量级的实时通信协议,它比 WebSocket 更容易实现和维护,因为它使用了标准的 HTTP 协议,而不需要额外的握手和协议。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/650e711d95b1f8cacd797c7a