Think-Swoole之WebSocket訊息、廣播以及 Swoole 原生方法呼叫

2020-10-19 15:00:18
Think-Swoole 教學之WebSocket 訊息、廣播以及 Swoole 原生方法呼叫

什麼是使用者端的 fd

fd 是在 Swoole 中使用者端的唯一識別符號,fd 是複用的,當連線關閉後 fd 會被新進入的連線複用,正在維持的 TCP 連線 fd 不會被複用。

獲取當前使用者端的fd

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
    /**
     * 事件監聽處理
     *
     * @return mixed
     */
    public function handle($event,Websocket $ws)
{
//        $ws = app('think\swoole\Websocket'); // 單例
        //獲取當前傳送訊息使用者端的 fd
        var_dump($ws -> getSender());
    }
}

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('連線成功');
    }
    ws.onmessage = function(data){
        console.log(data.data);
    }
    ws.onclose = function(){
        console.log('連線斷開');
    }
    function send()
{
        var message = document.getElementById('message').value;
        var to = document.getElementById('to').value;
        console.log("準備給" + to + "傳送資料:" + message);
        ws.send(JSON.stringify(['test',{
            to:to,
            message:message
        }])); //傳送的資料必須是 ['test',資料] 這種格式
    }
</script>
</body>
</html>

瀏覽器開啟多個標籤,來模擬多個使用者端連線,均存取 test.html 檔案,控制檯將會列印出每個使用者端的 fd ,如下圖我們開啟三個標籤進行存取:

547cdcfe630d9cd9328df012b72e9ff.png

也就是說,伺服器端傳送過來的訊息,都會被 HTML 中的 ws.onmessage 接收到。

給指定 fd 的使用者端傳送訊息(單發、群發)

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 = app('think\swoole\Websocket'); // 單例
        //獲取當前傳送訊息使用者端的 fd
        var_dump($ws -> getSender());
        //傳送給指定 fd 的使用者端,包括傳送者自己
        $ws -> to(intval($event['to'])) -> 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 的使用者端:

82eec924788243f9272d0fbbc528aed.png

傳送後,可見只有 fd 為 1、2 的使用者端能收到訊息(也就是說訊息發出者自身也會收到訊息),而 fd 為 3 的使用者端卻沒有收到訊息:

65fa9245ede5380ad675f5b8cf3b371.png

傳送後,可見只有 fd 為 1、2 的使用者端能收到訊息(也就是說訊息發出者自身也會收到訊息),而 fd 為 3 的使用者端卻沒有收到訊息:

ca5a7a20d3ee5587d070f1bf6febe73.png

傳送廣播訊息

廣播訊息就是傳送一條訊息給所有使用者端,但是不包括自己。

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
    /**
     * 事件監聽處理
     *
     * @return mixed
     */
    public function handle($event,Websocket $ws)
{
        //獲取當前傳送訊息使用者端的 fd
        var_dump($ws -> getSender());
        //傳送廣播訊息
        $ws -> broadcast() -> emit('testcallback',$event['message']);
    }
}

$ws -> broadcast() 方法就是傳送廣播訊息。

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

模擬使用者端給另一個使用者端發訊息

假設我當前 fd 為 1,但是我要模擬 用 fd 為 2 的使用者端給 fd 為 3 的使用者端傳送訊息,只需設定傳送者 fd 和接收者兩個 fd 即可:

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

經測試,1 沒有收到訊息,2 和 3 都收到了。

獲取 Swoole\WebSocket\Server

假設說我們現在需要一個功能,判斷一個使用者端是否為有效使用者端,即是否與伺服器端握手成功。Think-Swoole 擴充套件中沒有這個功能,但是查閱 Swoole 官方檔案,有個 isEstablished 函數可以完成我們需要的功能,那麼怎樣通過 Think-Swoole 拿到原生 Swoole 函數呢,答案就是獲取 Swoole\WebSocket\Server 這個類。有兩種方式:

1、app('swoole.server');

2、app('think\swoole\Manager') -> getServer();

範例化後,就可以呼叫 Swoole 原生方法了,如:

$manager = app('think\swoole\Manager');
$manager -> getServer() -> isEstablished(2);

附:\think\Swoole\Websocket類物件方法:

  • broadcast 設定進行廣播訊息傳送

  • isBroadcast 判斷當前是否是廣播模式

  • to 設定收件人 fd 或聊天室名(可以陣列設定多個)

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

  • join 當前使用者端加入到指定聊天室(可以多個)

  • leave 當前使用者端離開指定聊天室(可以多個)

  • emit 訊息傳送

  • close 關閉當前連線

  • getSender 獲取當前使用者端 id(即fd)

  • setSender 設定發件人的 fd

以上就是Think-Swoole之WebSocket訊息、廣播以及 Swoole 原生方法呼叫的詳細內容,更多請關注TW511.COM其它相關文章!