什麼是使用者端的 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 ,如下圖我們開啟三個標籤進行存取:
也就是說,伺服器端傳送過來的訊息,都會被 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 的使用者端:
傳送後,可見只有 fd 為 1、2 的使用者端能收到訊息(也就是說訊息發出者自身也會收到訊息),而 fd 為 3 的使用者端卻沒有收到訊息:
傳送後,可見只有 fd 為 1、2 的使用者端能收到訊息(也就是說訊息發出者自身也會收到訊息),而 fd 為 3 的使用者端卻沒有收到訊息:
傳送廣播訊息
廣播訊息就是傳送一條訊息給所有使用者端,但是不包括自己。
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其它相關文章!