Think-Swoole之WebSocket消息、广播以及 Swoole 原生方法调用

think-swoole 教程之websocket 消息、广播以及 swoole 原生方法调用

什么是客户端的 fd

fd 是在 Swoole 中客户端的唯一标识符,fd 是复用的,当连接关闭后 fd 会被新进入的连接复用,正在维持的 TCP 连接 fd 不会被复用。

获取当前客户端的fd

app/listener/WsConnect.php

<?php declare (strict_types = 1); namespace applistener; use thinkswooleWebsocket; class WsTest {     /**      * 事件监听处理      *      * @return mixed      */     public function handle($Event,Websocket $ws) { //        $ws = app(&#39;thinkswooleWebsocket&#39;); // 单例         //获取当前发送消息客户端的 fd         var_dump($ws -> getSender());     } }

test.html

nbsp;HTML&gt;       <meta>     <title>Document</title> 消息:<input> 接收者:<input><button>发送</button> <script>     var ws = new WebSocket("ws://127.0.0.1:9501/");     ws.onopen = function(){         console.log(&#39;连接成功&#39;);     }     ws.onmessage = function(data){         console.log(data.data);     }     ws.onclose = function(){         console.log(&#39;连接断开&#39;);     }     function send() {         var message = document.getElementById(&#39;message&#39;).value;         var to = document.getElementById(&#39;to&#39;).value;         console.log("准备给" + to + "发送数据:" + message);         ws.send(JSON.stringify([&#39;test&#39;,{             to:to,             message:message         }])); //发送的数据必须是 [&#39;test&#39;,数据] 这种格式     } </script>

浏览器打开多个标签,来模拟多个客户端连接,均访问 test.html 文件,控制台将会打印出每个客户端的 fd ,如下图我们打开三个标签进行访问:

Think-Swoole之WebSocket消息、广播以及 Swoole 原生方法调用

也就是说,服务端发送过来的消息,都会被 HTML 中的 ws.onmessage 接收到。

给指定 fd 的客户端发送消息(单发、群发)

app/listener/WsTest.php

<?php declare (strict_types = 1); namespace applistener; use thinkswooleWebsocket; class WsTest {     /**      * 事件监听处理      *      * @return mixed      */     public function handle($event,Websocket $ws) { //        $ws = app(&#39;thinkswooleWebsocket&#39;); // 单例         //获取当前发送消息客户端的 fd         var_dump($ws -> getSender());         //发送给指定 fd 的客户端,包括发送者自己         $ws -&gt; to(intval($event['to'])) -&gt; emit('testcallback',$event['message']);     } }

$ws -> to()是设置收件人 fd 或聊天室名,如果发送给多个人可以数组设置多个,例如 [1,2,3],fd 须为整型。$ws -> emit() 是发送消息方法,第一个参数是事件名称,用于多场景,可任意定义,就如上一片文章中客户端给服务端发送消息的 Test 一样。第二个参数是发送的内容,可以是字符串、数组,单独调用不设置收件人的话,就是发送消息给当前 fd 。

重启 Think-Swoole 服务,分别打开三个客户端进行连接,fd 分别为 1、2、3,现在,现在,我们用 fd 为 1 的客户端,发消息给 fd 为 2 的客户端:

Think-Swoole之WebSocket消息、广播以及 Swoole 原生方法调用

发送后,可见只有 fd 为 1、2 的客户端能收到消息(也就是说消息发出者自身也会收到消息),而 fd 为 3 的客户端却没有收到消息:

Think-Swoole之WebSocket消息、广播以及 Swoole 原生方法调用

发送后,可见只有 fd 为 1、2 的客户端能收到消息(也就是说消息发出者自身也会收到消息),而 fd 为 3 的客户端却没有收到消息:

Think-Swoole之WebSocket消息、广播以及 Swoole 原生方法调用

发送广播消息

广播消息就是发送一条消息给所有客户端,但是不包括自己。

app/listener/WsConnect.php

<?php declare (strict_types = 1); namespace applistener; use thinkswooleWebsocket; class WsTest {     /**      * 事件监听处理      *      * @return mixed      */     public function handle($event,Websocket $ws) {         //获取当前发送消息客户端的 fd         var_dump($ws -> getSender());         //发送广播消息         $ws -&gt; broadcast() -&gt; emit('testcallback',$event['message']);     } }

$ws -> broadcast() 方法就是发送广播消息。

但是如果想自己也收到广播消息,那就需要增加一条 $ws -> to($ws -> getSender()) -> emit(‘testcallback’,$event[‘message’]); 即可。

模拟客户端给另一个客户端发消息

假设我当前 fd 为 1,但是我要模拟 用 fd 为 2 的客户端给 fd 为 3 的客户端发送消息,只需设置发送者 fd 和接收者两个 fd 即可:

$ws -&gt; setSender(2) -&gt; to(3) -&gt; emit('testcallback',$event['message']);

经测试,1 没有收到消息,2 和 3 都收到了。

获取 SwooleWebSocketServer

假设说我们现在需要一个功能,判断一个客户端是否为有效客户端,即是否与服务端握手成功。Think-Swoole 扩展中没有这个功能,但是查阅 Swoole 官方文档,有个 isEstablished 函数可以完成我们需要的功能,那么怎样通过 Think-Swoole 拿到原生 Swoole 函数呢,答案就是获取 SwooleWebSocketServer 这个类。有两种方式:

1、app(‘swoole.server’);

2、app(‘thinkswooleManager’) -> getServer();

实例化后,就可以调用 Swoole 原生方法了,如:

$manager = app('thinkswooleManager'); $manager -&gt; getServer() -&gt; isEstablished(2);

附:thinkSwooleWebsocket类对象方法:

  • broadcast 设置进行广播消息发送

  • isBroadcast 判断当前是否是广播模式

  • to 设置收件人 fd 或聊天室名(可以数组设置多个)

  • getTo 获取收件人 fd 或聊天室名

  • join 当前客户端加入到指定聊天室(可以多个)

  • leave 当前客户端离开指定聊天室(可以多个)

  • emit 消息发送

  • close 关闭当前连接

  • getSender 获取当前客户端 id(即fd)

  • setSender 设置发件人的 fd

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享