如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理

发布时间:2021-09-18 10:16:00 作者:柒染
来源:亿速云 阅读:125

本篇文章为大家展示了如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理 ,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理

之前在网上翻了半天,也没有找到关于如何 通过 laravel-echo 主动发送消息laravel-websockets 中自定义控制器 的文章或教程。无奈之下只能翻 laravel-echolaravel-websockets 的源码了,小有收获。在此为有需要的朋友指个方向,少踩一个坑。

在使用 laravel-echo 时,网页想主动向服务器发送消息该怎么做呢?首先,最简单的就是 Ajax 异步请求了,写起来很容易。还有一种方式就是通过 websocket 了,既然已经建立了 socket 连接,我们何不利用他来进行双向通信呢!

如何使用 laravel-echo 通过 websocket 进行反向通信(这里的「反向」指从网页向服务器发送消息)。

简述

网页默认连接的 websocket 地址是 http://<your.host>:<wsPort>/app/<key>。url 中的 /app/ 部分是 pusher 中规定的,目前还无法修改。<key> 指实例化 Echo 时的参数「key」,同时也是.env 文件中的 PUSHER_APP_KEY 环境变量。服务器端控制器是 laravel-websockets 已经定义好的控制器:BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler。现在我们要实现自己的控制器,来做在线状态管理,所以就需要改变网页默认连接的 websocket 地址和后台控制器。

修改前端监听地址

打开 resources/views/hellow.blade.php 视图文件,在初始化 Echo 中的参数部分加入 wsPath 变量。此时 websocket 监听的地址就会变为 http://<your.host>:<wsPort><wsPath>/app/<key>

        window.Echo = new Echo({broadcaster: 'pusher',key: 'joker',// 在 socket 链接中设置 url 路径wsPath: '/liam/hao',wsHost: location.hostname,wsPort: 2020,forceTLS: false,});

注意:wsPath 变量一定要用 “/” 开头,否则会报错的

技巧:这里再提一个小知识点吧,pusher 默认会在连接 websocket 时发送 http://sockjs.pusher.com/pusher 请求,如果看着别扭(我不喜欢在网站中出现自己控制范围外的事情),可以在初始化 Echo 的参数中加一个 enabledTransports 变量,值是 ['ws', 'wss']。这样 pusher 就会将 http://sockjs.pusher.com/pusher 请求替换为你自己的 websocket 连接地址:

        window.Echo = new Echo({..// 加上这个参数后,就不会再向 http://sockjs.pusher.com/pusher 发送请求了enabledTransports: ['ws', 'wss'],});


后端添加新的路由

因为前端改变了监听地址。对应的后端,也需要新增一个对应的路由。我们打开 routes/web.php 文件,加入以下新路由:

Route::get('/login', function () {return view('login');});// 这个是 laravel-websockets 提供的门面方法,用来注册自定义的 websocekt 路由// WebSocketsRouter 绑定的实际对象是 BeyondCode\LaravelWebSockets\Server\Router 有兴趣的可以瞅瞅\BeyondCode\LaravelWebSockets\Facades\WebSocketsRouter::webSocket('/liam/hao/app/{appKey}', \App\Http\Controllers\MyWebsocketHandler::class);

创建自定义控制器

上面的路由中绑定了一个 App\Http\Controllers\MyWebsocketHandler 类,现在我们就来实现这个类:

> php artisan make:controller MyWebsocketHandler
Controller created successfully.

执行上面的命令后,我们会在 app/Http/Controllers 文件夹中找到 MyWebsocketHandler.php 文件,我们来进行一些修改:

<?phpnamespace App\Http\Controllers;use BeyondCode\LaravelWebSockets\WebSockets\Messages\PusherMessageFactory;use BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler;use Ratchet\ConnectionInterface;use Ratchet\RFC6455\Messaging\MessageInterface;// 注意这里要继承自 WebSocketHandlerclass MyWebsocketHandler extends WebSocketHandler{public function onMessage(ConnectionInterface $connection, MessageInterface $message){var_dump(json_decode($message->getPayload()));$message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);$message->respond();}public function onClose(ConnectionInterface $connection){$this->channelManager->removeFromAllChannels($connection);var_dump('close');}}

好了,我们现在来小测一下,看看新的路由有没有生效。重启 laravel-websockets 的 http 服务。打开浏览器的开发者工具,然后刷新页面。如果像下图一样,在命令行终端里看到了我们 var_dump() 的数据,那就说明新的路由和控制器已经连通了:

「手把手」利用laravel-echo主动向服务端发送消息,实现在线状态管理

注意:MyWebsocketHandler 并不是一般的 Controller,他需要继承自 BeyondCode\LaravelWebSockets\WebSockets\WebSocketHandler。如果你需要控制更多逻辑,可直接实现 Ratchet\WebSocket\MessageComponentInterface 接口,并自己实现 onOpen()onClose()onMessage() 等方法。

前端发送消息(重点)

重点来了哈,虽说是重点,但代码很简单:

        Echo.channel('abcdefg.'+uuid).listen('LoginedEvent', (e) => {console.log(e);var session_id = e.session_id;location.href = location.origin+'/hello?session_id='+session_id;});// 我们在这里放置一个定时器,每三秒钟向服务器发送一条数据setInterval(function(){// 这里新增一个向服务端发送消息的方法// 第一个参数是事件名,这个可以随意写,不需要与 Laravel 中做对应// 第二个参数是具体数据,这个就更随意了Echo.connector.pusher.send_event('hi_girl', {my_name: 'LiamHao',my_height: 180,});}, 3000);

是不是很简单,我们再来小测一下,看看服务端接收到的数据是什么样子的:

如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理

后端已经接收到数据了。做到这里,想必有些基础的朋友应该已经可以做自己想做的事情了。

设置在线状态

这里我们就不做太复杂了数据库操作了,还是老样子,以最简单的方式,用 缓存 做记录吧。我们在 App\Http\Controllers\MyWebsocketHandleronMessage()onClose() 方法中分别加入记录状态的代码:

    public function onMessage(ConnectionInterface $connection, MessageInterface $message){var_dump(json_decode($message->getPayload()));// 每当收到消息时,设置当前连接状态为“在线”,60 秒后过期\Cache::put('socekt-status', ['socket_id' => $connection->socketId,'status' => '在线',], 60);$message = PusherMessageFactory::createForMessage($message, $connection, $this->channelManager);$message->respond();}public function onClose(ConnectionInterface $connection){$this->channelManager->removeFromAllChannels($connection);var_dump('close');// 浏览器主动断开连接时,设置当前连接状态为“离线”,不设置过期时间\Cache::put('socekt-status', ['socket_id' => $connection->socketId,'status' => '离线',]);}

然后修改下 resources/views/login.blade.php 视图文件,在页面中显示连接的状态:

    <body><input type="text" name="username"><input type="text" name="password"><button>登陆</button><!-- 我们在这里简单的展示一下连接的状态 --><h2>Websocket 连接列表</h2><!-- 用 blade 模板语法渲染数据,简单的打印下数据 --><pre>{{ var_export(\Cache::get('socekt-status')) }}</pre></body>

大功告成,我们来看下效果。先打开 http://<your.host>/login 页面,此时未显示任何内容。这是正常的,因为 Cache 中还没有记录任何信息。接下来再打开 http://<your.host>/hello 页面,看下浏览器开发者工具中 websocket 已连接成功。下面见证奇迹的时刻到了,我们再将 http://<your.host>/login 页面刷新一次,此时会看到 Cache 中记录的在线状态信息:

「手把手」利用laravel-echo主动向服务端发送消息,实现在线状态管理

我们再来试下断开 websocekt 连接时,是否会显示离线。将 http://<your.host>/hello 页面直接关闭,也就是点标签页上的「叉子」。再刷新下 http://<your.host>/login 页面:

如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理

上述内容就是如何通过laravel-echo主动向服务端发送消息以及实现在线状态管理 ,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. redis如何通过位图法记录在线用户的状态
  2. 使用vue怎么实现状态管理

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

上一篇:从双11业务看分布式事务满足Saga和异步场景的示例分析

下一篇:python中日期替换字母函数的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》