什麼是WebSocket
WebSocket 協定是基於TCP 的一種新的網路協議,使得客戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向客戶端推送資料。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向資料傳輸。
為什麼需要 WebSocket
因為 HTTP 的通訊只能由客戶端發起。
WebSocket有哪些特點
#建立在TCP協定之上的
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 WsTestapp/ listener 目錄下會產生剛才建立的監聽類別文件,在對應的事件類別中可寫入業務邏輯。我們這裡先印出 $event 這個變數。 Connect 事件中的 $event 是 app\Request 請求對象,Test自訂訊息接收事件的 $event 是客戶端發送過來的訊息。 3、在app/event.php 中的陣列listen 鍵中定義事件監聽類別:
app/event.php 'listen' => [ 'AppInit' => [], 'HttpRun' => [], 'HttpEnd' => [], 'LogLevel' => [], 'LogWrite' => [], //监听连接,swoole 事件必须以 swoole 开头 'swoole.websocket.Connect' => [ app\listener\WsConnect::class ], //监听关闭 'swoole.websocket.Close' => [ \app\listener\WsClose::class ], //监听 Test 场景 'swoole.websocket.Test' => [ \app\listener\WsTest::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' => 'app\listener\WsConnect', 'close' => 'app\listener\WsClose', 'test' => 'app\listener\WsTest' ],4、專案根目錄開啟服務:php think swoole start 即可,底層會自動判斷目前請求是HTTP 還是WebSocket。 客戶端與服務端建立連線現在我們做一個 HTML 頁面,透過 HTML5 WebSocket 向我們的伺服器端建立連線。在任意地方新建 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); } 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>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 頁面,並開啟瀏覽器偵錯控制台,可以看到連線成功的字樣,以及服務端列印出來的參數: 然後我們在剛才創建的HTML 頁面的輸入框中發送訊息,控制台中列印出了我們的訊息:
Swoole 監聽服務終端機中,也收到了我們發送過來的訊息:
這是因為我們在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 參數取得的就是它。
以上是Think-Swoole教程之WebSocket的介紹、事件與資料發送的詳細內容。更多資訊請關注PHP中文網其他相關文章!