Think-Swoole教程之WebSocket的介紹、事件和數據發送

Think-Swoole教程之WebSocket的介紹、事件和數據發送

什么是 websocket

WebSocket 協議是基于 TCP 的一種新的網絡協議,使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。

為什么需要 WebSocket

因為 http 的通信只能由客戶端發起。

WebSocket有哪些特點

  • 建立在TCP協議之上的

  • 性能開銷小,通信高效

  • 客戶端可以與任意的服務器進行通信

  • 協議標識:ws、wss

  • 持久化網絡通信協議

WebSocket 使用場景

社交聊天、彈幕、多玩家游戲、協同編輯、股票基金實時報價、體育實況更新、視頻會議聊天、基于位置的應用、在線教育等需要高實時性的運用場景。

在 WebSocket 之前,傳統方式我們想要做聊天程序,可能會使用 JavaScript 定時器,每隔一秒鐘發送一次 HTTP 請求到服務器,查詢有沒有新消息。

有了 WebSocket ,客戶端通過瀏覽器以 HTTP 方式向服務端發送 WebSocket 連接請求,然后服務器發出回應,這個過程通常稱為“握手” 。瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道,將協議升級為 WebSocket,有新消息的話,服務端主動將消息推送給客戶端。

SocketIO 又是什么

WebSocket 是 html5 最新提出的規范,雖然主流瀏覽器都已經支持,但仍然可能有不兼容的情況,為了兼容所有瀏覽器,給程序員提供一致的編程體驗, SocketIO 將 WebSocket 、ajax 和其它的通信方式全部封裝成了統一的通信接口,也就是說,我們在使用 SocketIO 時,不用擔心兼容問題,底層會自動選用最佳的通信方式。因此說,WebSocket 是 SocketIO 的一個子集,Think-swoole 中是按照 SocketIO 進行解析發送到服務端的數據。

在 Thinkphp 6 中開啟 WebSocket 服務

1、配置文件 config/swoole.php 中“websocket. enable”設置為 true。

2、創建監聽事件,創建WsConnect、WsClose、WsTest(這個可任意命名,和客戶端須對應起來),在項目根目錄分別輸入如下命令:

php?think?make:listener?WsConnect php?think?make:listener?WsClose php?think?make:listener?WsTest

app/listener 目錄下會生成剛才創建的監聽類文件,在對應的事件類中可寫入業務邏輯。我們這里先打印 $Event 這個變量。Connect 事件中的 $event 是 appRequest 請求對象,Test自定義消息接收事件的 $event 是客戶端發送過來的消息。

3、在 app/event.php 中的數組 listen 鍵中定義事件監聽類:

app/event.php 'listen'????=>?[ ????????'AppInit'??=>?[], ????????'HttpRun'??=>?[], ????????'HttpEnd'??=>?[], ????????'LogLevel'?=>?[], ????????'LogWrite'?=>?[], ????????//監聽連接,swoole?事件必須以?swoole?開頭 ????????'swoole.websocket.Connect'?=>?[ ????????????applistenerWsConnect::class ????????], ????????//監聽關閉 ????????'swoole.websocket.Close'?=>?[ ????????????applistenerWsClose::class ????????], ????????//監聽?Test?場景 ????????'swoole.websocket.Test'?=>?[ ????????????applistenerWsTest::class ????????], ????],

swoole.websocket.Connect:客戶端與服務器建立連接并完成握手事件,即 Swoole 中的 onOpen 事件。在這里記錄你自己程序用戶與客戶端的連接ID(fd)等。非必須,建議定義。

swoole.websocket.Close:客戶端連接關閉事件,非必須。

swoole.websocket.Test:自定義的 Test 事件;用于接收客戶端發送的 test 事件的消息。一個項目中可以定義多個 Test 事件,例如聊天、定位、客服功能事件,則可對應為 Test1、Test2、Test3等。

WebSocket 的事件也可以在 config/swoole.php 配置文件的“websocket. listen”進行配置:

'listen'?=>?[ ????//?首字母大小寫都可以;值應該是字符串非數組 ????'connect'?=>?'applistenerWsConnect', ????'close'???=>?'applistenerWsClose', ????'test'????=>?'applistenerWsTest' ],

4、項目根目錄開啟服務:php think swoole start 即可,底層會自動判斷當前請求是 HTTP 還是 WebSocket。

客戶端與服務端建立連接

現在我們做一個 HTML 頁面,通過 html5 WebSocket 向我們的服務器端建立連接。在任意地方新建 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);     }     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>

HTML5 WebSocket 有關介紹,可以訪問這里進行學習。

前端代碼中 var ws = new WebSocket(“ws://127.0.0.1:9501/”); 我的服務器是在本地,swoole.php 配置文件中配置的端口號是 9501,所以訪問127.0.0.1:9501,ws 是 WebSocket 協議,與 HTTP、https 一樣,它有 WS 和 WSS 協議。ws.onmessage 可以接受消息。

接下來通過瀏覽器訪問這個 HTML 頁面,并打開瀏覽器調試控制臺,可以看到連接成功的字樣,以及服務端打印出來的參數:

Think-Swoole教程之WebSocket的介紹、事件和數據發送

然后我們在剛才創建的 HTML 頁面的輸入框中發送消息,控制臺中打印出了我們的信息:

Think-Swoole教程之WebSocket的介紹、事件和數據發送

Swoole 監聽服務終端中,也收到了我們發送過來的消息:

Think-Swoole教程之WebSocket的介紹、事件和數據發送

這是因為我們在 app/listener/WsTest 打印了 $event 變量。

最后說明一下前端頁面中 ws.send(JSON.stringify([‘test’,{to:to,message:message}])); 這段代碼,JSON.stringify() 的作用是將 JavaScript 對象轉換為 JSON 字符串,to 和 message 屬性是我們自定義的,test 是后端定義的 Test 事件,這個名稱一定和后端對應起來。由于think-swoole中是按照 SocketIO 進行解析發送過來的數據,所以你發送的數據應該是 “[‘事件名’, 真正要發送的數據]” 的字符串形式:第一個參數的 test 就是對應服務器端的Test 事件,用于區分更多場景的實時通信邏輯業務;第二個參數才是你真正發送的數據,可以是字符串、數據、對象,服務器端 $event 參數獲取的就是它。

? 版權聲明
THE END
喜歡就支持一下吧
點贊11 分享