socket.io入門,簡易聊天室


介紹

通常我們web使用的是http協議,但是 HTTP 協議有一個缺陷:通信只能由客戶端發起。

所以我們需要一個可以由服務端主動發出的協議,即WebSocket。

WebSocket是HTML5新增的一種通信協議,其特點是服務端可以主動向客戶端推送信息,客戶端也可以主動向服務端發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。

Socket.IO 是一個基於 Node.js 的實時應用程序框架,在即時通訊、通知與消息推送,實時分析等場景中有較為廣泛的應用。

socket.io 包含兩個部分:

  • 服務器端(server):運行在 Node.js 服務器上
  • 客戶端(client):運行在瀏覽器中

開啟服務

當然,socket.IO構架在一個nodejs服務上,這里開啟一個express服務。

創建文件夾socketIODemo,然后安裝

    npm init -y
    npm install express --save

之后在socketIODemo中創建文件index.js:

    const express = require('express')
    const app = express()
    
    app.use(express.static(__dirname + '/public'));
    
    app.listen(3000, () => console.log('Example app listening on port 3000!'))

創建靜態資源public/index.html :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            html,
            body {
                height: 100%;
                overflow: hidden;
            }
            .chat {
                float: left;
                padding: 1em 1em 0 2em;
                height: 100%;
                width: 500px;
                border-right: 1px solid #DA4;
                overflow-y: scroll;
            }
            .inputpart {
                float: left;
                margin-left: 10px;
            }
            #userName {
                font-size: 20px;
                color: rgb(3, 57, 109);
            }
        </style>
    </head>
    <body>
        <div class="chat">
            <ul id="messages">
                //聊天信息
            </ul>
        </div>
        <div class="inputpart">
            <div id="userName">
    			//用來展示用戶id
            </div>
            <form action="">
                <input autocomplete="off" id="inpB" /><button id="say">Send</button>
            </form>
        </div>
    </body>
    </html>

此時開啟服務: node index, 訪問localhost:3000。

服務開啟!

使用socket.IO

安裝:

    npm install socket.io --save

然后在index.js中注冊socket.io,並改為http監聽:

    let http = require('http').Server(app)
    const io = require('socket.io')(http) 
    app.use(express.static(__dirname + '/public'));
    
    http.listen(3000, () => console.log('Example app listening on port 3000!'))

此時服務已改為WebSocket服務。

數據傳輸

服務端運行后會在根目錄動態生成socket.io的客戶端js文件,客戶端可以通過固定路徑/socket.io/socket.io.js添加引用。
在HTML中引用js文件,並調用:

        <script src="/socket.io/socket.io.js"></script>
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script>
            $(function () {
                var userName = '';
                while ($('#userName').text().trim() === '') {
                    //設置用戶名
                    let promptName = prompt("請設置你的昵稱", "")
                    userName = promptName ? promptName + ':' : '未命名:';
                    $('#userName').text(userName);
                }
                let socket = io();
                socket.on('connect', function () {
                    socket.emit('join', userName)
                })
                // 監聽系統消息
                socket.on('sys', function (sysMsg) {
                    var message = '<div class="sysMsg">' + sysMsg + '</div>';
                    $('#messages').append(message);
                });
            })
        </script>

這段代碼中,socket.on('connect', function () { })為默認監聽事件,socket.io 提供了默認事件(如:connect, message, disconnect)。也可以自定義。socket.emit('action');表示發送了一個action命令,命令是字符串的。

后台index.js文件中:

    io.on('connection', function (socket) {
        console.log('a user connected')
        let userID = ''
        socket.on('join', function (userName) {
            userID = userName;
            io.emit('sys', userID + '已加入房間');
            console.log(userID + '加入了');
        });
    })

connection事件在客戶端成功連接到服務端時觸發,有了這個事件,我們可以隨時掌握用戶連接到服務端的信息。
當客戶端成功建立連接時,在connection事件的回調函數中,我們還是可以為socket注冊一些常用的事件,如:disconnect事件socket.on('disconnect',function(){...});,它在客戶端連接斷開是觸發,這時候我就知道用戶已經離開了。

重啟服務,打開多個窗口,查看聊天框內容:

下面添加聊天功能。

在HTML文件中添加事件監聽click:

      $('#say').click((e) => {
          e.preventDefault()
          socket.send($("#inpB")[0].value)
          $("#inpB")[0].value = ''
      })
      socket.on('msg', function (userName, userColor, msg) {
          var message = ' <div class="message">' +
              `<span class="user" style="font-size:1.5em; color: #${userColor}">` + 	             userName + '</span>' +
              '  <span class="msg">' + msg + '</span>' +
              '</div>';
          $('#messages').append(message);
          // 滾動條保持最下方
          $('#messages').scrollTop($('#messages')[0].scrollHeight);
      });

這段代碼中,首先監聽事件並將input中內容send回去;socket.on為自定義事件msg 用來接收后台發送來的其他人的發言。

socket.emit和socket.send的區別在stackoverflow中有一個解釋大意是說emit可以自定義事件,而send不可以,且只能以message接收。

后台index.js:

    io.on('connection', function (socket) {
        console.log('a user connected')
        let userID = '', userColor =parseInt(Math.random() * 16777216).toString(16)
    
        socket.on('join', function (userName) {
            userID = userName;
            io.emit('sys', userID + '已加入房間');
            console.log(userID + '加入了');
        });
        socket.on('message', function (msg){
            io.emit('msg', userID, userColor, msg)
        })
    })

為新的成員隨機匹配顏色,並將message監聽到的信息通過自定義為msg的事件emit出去。

此時,一個簡易聊天室已經完成。

讀者可以自行添加退出功能,或者設置多個房間。。。

參考:https://www.jianshu.com/p/40d8bc17529f


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM