首頁  >  文章  >  php框架  >  利用webSocket與Swoole打造一個小型聊天室

利用webSocket與Swoole打造一個小型聊天室

谨言慎行
谨言慎行原創
2020-11-09 20:01:102241瀏覽

前言

    這次只記錄 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

  1. onopen() 發起連接,連線成功後執行。
  2. onclose() 連線中斷後執行。
  3. onmessage() 收到服務端訊息後執行。
  4. onerror() 伺服器異常執行。
    其實,webSocket 就這些常用方法,也沒啥特殊要求的,他就是作為一個保持連接,接收伺服器狀態的一個瀏覽器的 API 存在,非常簡潔方便。

前端頁碼:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>打工人聊天室</title>   <!--需要引入jq 文件--></head><style>    .content {        height: 400px;        max-width: 400px;        overflow: auto;        border-radius: 5px;        border: 1px solid #f0f0f0;    }</style><body>            <div id="content" class="content">                <p>聊天区域</p>            </div>            你好打工人:<samp id="nickname">昵称</samp> <br>            本次连接FD: <samp id="fd-samp"></samp> <br>            <input type="text" id="msg">            <input type="hidden" id="fd" value="">            <button id="send" onclick="send()">发送</button></body></html>

JS 代碼:

    在伺服器資訊回執時,會有第一次連接回執,還是服務端發送訊息回執的狀態區別,透過msgType 分辨,如果是第一次連線的回執訊息,則把FD 做一個頁面留存,並不顯示在聊天訊息區,如果收到的是訊息回執,就直接顯示到聊天訊息區。

    還有就是,前後端互相通訊發送的東西,都是字串性質最優,我前端處理的方法是先組合成一個對象,然後轉 JSON 串。

<script>    //滚动条最底部    function scrolltest() {        var div = document.getElementById("content");        div.scrollTop = div.scrollHeight;    }    var wsServer = &#39;ws://127.0.0.1:9502&#39;;    var websocket = new WebSocket(wsServer);    var nickname = Math.random().toString(36).substr(2);    thisFd = &#39;&#39;;    $(&#39;#nickname&#39;).html(nickname);    //点击发送    function send() {        var msg = $(&#39;#msg&#39;).val();        var data = {            &#39;nickname&#39;: nickname,            &#39;fd&#39;: thisFd,            &#39;data&#39;: msg        }        //生成json 方便后台接收以及使用        var data = JSON.stringify(data);        websocket.send(data);        //然后清空        $(&#39;#msg&#39;).val(&#39;&#39;);    }    //链接成功    websocket.onopen = function (evt) {        $("#content >p:last-child").after(&#39;<p> 服务器已连接,开始聊天吧 </p>&#39;);    };    //链接断开    websocket.onclose = function (evt) {        $("#content >p:last-child").after(&#39;<p> 服务器已断开,请重新连接 </p>&#39;);    };    //收到服务器消息    websocket.onmessage = function (evt) {        //握手成功后,会接受到服务端返回的fd ,msgType = 1        //字符串格式化成json        var data = eval(&#39;(&#39; + evt.data + &#39;)&#39;);        // console.log(evt.data);        switch (data.msgType) {            case 1:                thisFd = data.fd;                $(&#39;#fd-samp&#39;).html(thisFd);                $(&#39;#fd&#39;).val(thisFd);                break;            case 2:                if (data.nickname == nickname) {                    data.nickname = &#39;我&#39;;                }                $("#content >p:last-child").after(&#39;<p>&#39; + data.nickname + &#39; 在 &#39; + data.time + &#39; 说:<br>&#39; + data.data + &#39;</p>&#39;);                //接收到消息自动触底                scrolltest();                break;        }    };    //服务器异常    websocket.onerror = function (evt, e) {        $("#content >p:last-child").after(&#39;<p> 服务器异常 </p>&#39;);    };</script>

服務端程式碼
    服務端需要 callback 前端過來的訊息,轉換為物件數據,然後增加點自訂資料直接原樣返回,並且群發到前端。

<?php    //创建WebSocket Server对象,监听0.0.0.0:9502端口    $ws = new Swoole\WebSocket\Server(&#39;0.0.0.0&#39;, 9502);    //监听WebSocket连接打开事件    $ws->on(&#39;open&#39;, function ($ws, $request){        $fd = $request->fd;        $data = json_encode([            &#39;fd&#39; => $request->fd,            &#39;msgType&#39; => 1  //代表第一次连接,前端处理fd        ]);        $ws->push($request->fd, $data);    });    //监听WebSocket消息事件    $ws->on(&#39;message&#39;, function ($ws, $frame) {        $stats = $ws->stats();        //格式化接收到json        $data = json_decode($frame->data);        // 原基础上不动,增加一些自定义        $data->msgType = 2; //代表服务器端回复        $data->time = date(&#39;Y-m-d H-i-s&#39;);        $data = json_encode($data);        //因为是聊天室,所以包括自己都需要收到回执,就直接群发 swoole 提供 connections 方法 包含了所有在线的 fd        foreach ($ws->connections as $conn_fd){            $ws->push($conn_fd,$data);        }    });    //监听WebSocket连接关闭事件    $ws->on(&#39;close&#39;, function ($ws, $fd) {//        echo "client-{$fd} is closed\n";    });    $ws->start();

程式碼齊全之後,接下來就只需要在控制台執行以下 PHP 檔案就行。

然後前台直接訪問你的網站地址,我的是本地127.0.0.1

多開幾個視窗模擬多個用戶,然後發送訊息測試即可:

你好,打工人。

程式碼很簡單,難度不大,但可以很簡潔的反應出 webScoket 和 Swoole 的一種強大。

以上是利用webSocket與Swoole打造一個小型聊天室的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn