ホームページ  >  記事  >  PHPフレームワーク  >  Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

藏色散人
藏色散人転載
2020-10-20 13:43:592933ブラウズ

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

WebSocket クライアント メッセージの解析

クライアントがサーバーに接続すると、接続イベントがトリガーされることを前に示しました。イベントの場合、現在のクライアントの fd を返します。クライアントがサーバーにメッセージを送信すると、サーバーはルールに従って指定された fd のクライアントにメッセージを送信します:

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace app\listener;
class WsConnect
{
    /**
     * 事件监听处理
     *
     * @return mixed
     * 受用 WebSocket 客户端连接入口
     */
    public function handle($event)
{
        //实例化 Websocket 类
        $ws = app(&#39;\think\swoole\Websocket&#39;);
        //
        $ws -> emit(&#39;sendfd&#39;,$ws -> getSender());
    }
}

app/ listener/ WsTest.php

<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event,Websocket $ws)
{
        $ws -> to(intval($event[&#39;to&#39;])) -> emit(&#39;testcallback&#39;,$event[&#39;message&#39;]);
    }
}

クライアントが上記の 2 つのイベントを実行すると、コンソールに次の情報が出力されます。

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

先頭に数字がいくつかあります。返品情報の40、42とはどういう意味ですか?

使用する拡張機能は SocketIO プロトコルに基づいているため、これらの番号はプロトコル コードとして理解できます。

/vendor/topthink/think-swoole/src/websocket/socketio/Packet.php を開くと、次の内容があります:

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

上記はソケットのタイプ、以下はエンジンです 前後の 2 つのコード名を組み合わせると、

40:”MESSAGE CONNECT”
42:”MESSAGE EVENT”

これらのコードを組み合わせると、SocketIO でのメッセージの一般的な動作を知ることができます。

コンソールから出力されたメッセージから、これらのメッセージは直接使用できないため、インターセプトして処理する必要があることがわかりました:

test.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
消息:<input type="text" id="message">
接收者:<input type="text" id="to">
<button onclick="send()">发送</button>
<script>
    var ws = new WebSocket("ws://127.0.0.1:9501/");
    ws.onopen = function(){
        console.log(&#39;连接成功&#39;);
    }
    //数据返回的解析
    function mycallback(data){
        var start = data.indexOf(&#39;[&#39;) // 第一次出现的位置
        var start1 = data.indexOf(&#39;{&#39;)
        if(start < 0){
            start = start1;
        }
        if(start >= 0 && start1 >= 0){
            start = Math.min(start,start1);
        }
        if(start >= 0){
            console.log(data);
            var json = data.substr(start); //截取
            var json = JSON.parse(json);
            console.log(json);
        }
    }
    ws.onmessage = function(data){
        // console.log(data.data);
        mycallback(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>
</body>
</html>

解析されたデータ:

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

#SocketIO を使用してメッセージ ビジネスを処理する

SocketIO の関連知識については、クライアントの知識に重点を置いたドキュメントを参照してください:

https://www.w3cschool.cn/socket/socket-k49j2eia.html

iotest.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
消息:<input type="text" id="message">
接收者:<input type="text" id="to">
<button onclick="send()">发送</button>
<script src="./socketio.js"></script>
<script>
    //http 协议
    var socket = io("http://127.0.0.1:9501", {transports: [&#39;websocket&#39;]});
    socket.on(&#39;connect&#39;, function(){
        console.log(&#39;connect success&#39;);
    });
    socket.on(&#39;close&#39;,function(){
       console.log(&#39;connect close&#39;)
    });
    //send_fd 为自定义的场景值,和后端对应
    socket.on("sendfd", function (data) {
        console.log(data)
    });
    //testcallback 为自定义的场景值,和后端对应
    socket.on("testcallback", function (data) {
        console.log(data)
    });
    function send() {
        var message = document.getElementById(&#39;message&#39;).value;
        var to = document.getElementById(&#39;to&#39;).value;
        socket.emit(&#39;test&#39;, {
            //属性可自行添加
            to:to,
            message:message
        })
    }
</script>
</body>
</html>

varソケット = io("http://127.0.0.1:9501" , {transports: ['websocket']}); 2 番目のパラメーターは、アップグレードするプロトコルを指定します。

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace app\listener;
class WsConnect
{
    /**
     * 事件监听处理
     *
     * @return mixed
     * 受用 WebSocket 客户端连接入口
     */
    public function handle($event)
{
        //实例化 Websocket 类
        $ws = app(&#39;\think\swoole\Websocket&#39;);
        //
        $ws -> emit(&#39;sendfd&#39;,$ws -> getSender());
    }
}

app/listener/WsTest.php

<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event,Websocket $ws)
{
//        $ws -> to(intval($event[&#39;to&#39;])) -> emit(&#39;testcallback&#39;,$event[&#39;message&#39;]);
        $ws -> to(intval($event[&#39;to&#39;])) -> emit(&#39;testcallback&#39;,[
            &#39;form&#39; => [
                &#39;id&#39; => 10,
                &#39;fd&#39; => $ws -> getSender(),
                &#39;nickname&#39; => &#39;张三&#39;
            ],
            &#39;to&#39; => [
                &#39;id&#39; => 11,
                &#39;fd&#39; => intval($event[&#39;to&#39;]),
                &#39;nickname&#39; => &#39;李四&#39;
            ],
            &#39;massage&#39; => [
                &#39;id&#39; => 888,
                &#39;create_time&#39; => &#39;2020-03-13&#39;,
                &#39;content&#39; => $event[&#39;message&#39;]
            ]
        ]);
    }
}

2 つのクライアントを開きます。fd は 5 と 6:

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

WsConnect.php には $ws -> Emit('sendfd',$ws -> getSender()); あり、send fd メッセージに対応するシーンの値は「sendfd」です。 iotest.html には、socket.on("sendfd", function (data) {console.log(data)}); このコードには、シーン値 "sendfd" もあり、このコード行で直接取得できます。対応するシーン値情報なので、fd 値がコンソールに表示されます。

fd 5 を使用して fd 6 に情報を送信します:

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

両方のクライアントが情報を受信します:

Think-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理する

メッセージは、WsTest.php でシーン値 testcallback を指定するために送信され、iotest.html では、socket.on("testcallback", function (data){console) で送信されているため、メッセージが解析されたことがわかります。 .log(data)}); を使用して、解析結果を直接取得できます。

これは、クライアント メッセージを受信する際の SocketIO の利便性を示しています。

ユーザーUIDとクライアントfdのバインディング

これまでの例では、fdを指定してクライアントにメッセージを送信していましたが、実際にはfdによって送信オブジェクトを特定することは不可能です。 fd は固定されていないため、ユーザーの UID をクライアントの fd にバインドする必要があり、その後、fd を選択してメッセージの送信を完了できます。

フロントエンド ページの HTTP 接続に UID パラメータを追加するだけです:

test.html

var ws = new WebSocket("ws://127.0.0.1:9501/?uid=1");

iotest.html

var socket = io("http://127.0.0.1:9501?uid=1", {transports: [&#39;websocket&#39;]});

バックエンドは接続イベントでバインドできます:

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace app\listener;
class WsConnect
{
    /**
     * 事件监听处理
     *
     * @return mixed
     * 受用 WebSocket 客户端连接入口
     */
    public function handle($event)
{
        // $event 为请求对象
        //实例化 Websocket 类
        $ws = app(&#39;\think\swoole\Websocket&#39;);
        //获取 uid
        $uid = $event -> get(&#39;uid&#39;);
        //获取 fd
        $fd = $ws -> getSender();
        //获取到 uid 和 fd 后,可以存数据库,内存或者 redis
        $ws -> emit(&#39;sendfd&#39;,[
            &#39;uid&#39; => $uid,
            &#39;fd&#39; => $fd
        ]);
    }
}

UID と fd を使用すると、接続が成功するたびにデータベースを更新し、再起動できます。接続が切断された後、ユーザーの FD をクリアします。サーバーを再起動すると、両者の対応関係は役に立たなくなるため、データベースに保存する必要はなく、Redis に保存するのが最善です。また、両者の関係をマッピングすることも良い選択です。 Redis のハッシュを通じて。

以上がThink-Swoole の WebSocket クライアント メッセージを解析し、S​​ocketIO を使用してユーザー UID と fd アソシエーションを処理するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事は阿dai哥で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。