前言
這次只記錄 webSocket 與 Swoole 配合打造一個小型的聊天室,功能簡陋,但是可以作為一個很好的入門案例。
專案簡介
本來就是作為一個很小的案例來寫的,包含的功能點也不是那多,索性就按照最最低配置來搞。
能夠顯示聊天訊息的聊天區,同時兼顧顯示連結狀態,目前是否連接成功,或服務端是否斷開連接,而前端不知道的狀況。
一個輸入框,純粹的輸入框?
#點擊按鈕發送不刷新頁面,同時清空目前輸入框內容,就簡單的一個button 而已,點擊執行,不支援回車發送。
收到訊息,滾動條自動觸底,這個功能在某些使用場景是方便的,但又會造成某些場景使用不方便,方便在於有新訊息不需要人工滾動,不方便在於,可能你在看歷史消息,它自動觸底了…還需要根據自己實際需求優化一下下。
隨機暱稱,當然不需要保存,刷新即丟,在收到訊息如果是自己發送的,則顯示[ 我] 在某某時候發送了某某訊息,而不是顯示暱稱字串。
專案環境
直接貼上複製的
composer create-project topthink/think tpcd tpcomposer require topthink/think-swoole
因為是測試項目,所有的都是預設安裝,在安裝完之後,造訪前端頁面,使用view 方法會報錯,百度一下就有解決方案了。
webSocket 的使用
參考文件:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
- onopen() 發起連接,連線成功後執行。
- onclose() 連線中斷後執行。
- onmessage() 收到服務端訊息後執行。
- onerror() 伺服器異常執行。
其實,webSocket 就這些常用方法,也沒啥特殊要求的,他就是作為一個保持連接,接收伺服器狀態的一個瀏覽器的 API 存在,非常簡潔方便。
前端頁碼:
打工人聊天室 你好打工人:昵称聊天区域
本次连接FD:
JS 代碼:
在伺服器資訊回執時,會有第一次連接回執,還是服務端發送訊息回執的狀態區別,透過msgType 分辨,如果是第一次連線的回執訊息,則把FD 做一個頁面留存,並不顯示在聊天訊息區,如果收到的是訊息回執,就直接顯示到聊天訊息區。
還有就是,前後端互相通訊發送的東西,都是字串性質最優,我前端處理的方法是先組合成一個對象,然後轉 JSON 串。
服務端程式碼
服務端需要 callback 前端過來的訊息,轉換為物件數據,然後增加點自訂資料直接原樣返回,並且群發到前端。
on('open', function ($ws, $request){ $fd = $request->fd; $data = json_encode([ 'fd' => $request->fd, 'msgType' => 1 //代表第一次连接,前端处理fd ]); $ws->push($request->fd, $data); }); //监听WebSocket消息事件 $ws->on('message', function ($ws, $frame) { $stats = $ws->stats(); //格式化接收到json $data = json_decode($frame->data); // 原基础上不动,增加一些自定义 $data->msgType = 2; //代表服务器端回复 $data->time = date('Y-m-d H-i-s'); $data = json_encode($data); //因为是聊天室,所以包括自己都需要收到回执,就直接群发 swoole 提供 connections 方法 包含了所有在线的 fd foreach ($ws->connections as $conn_fd){ $ws->push($conn_fd,$data); } }); //监听WebSocket连接关闭事件 $ws->on('close', function ($ws, $fd) {// echo "client-{$fd} is closed\n"; }); $ws->start();
程式碼齊全之後,接下來就只需要在控制台執行以下 PHP 檔案就行。
然後前台直接訪問你的網站地址,我的是本地127.0.0.1
多開幾個視窗模擬多個用戶,然後發送訊息測試即可:
你好,打工人。
程式碼很簡單,難度不大,但可以很簡潔的反應出 webScoket 和 Swoole 的一種強大。