node+websocket創建簡易聊天室


關於websocket的介紹太多,在這就不一一介紹了,本文主要實現通過websocket創建一個簡易聊天室,就是90年代那種聊天室

服務端

1.安裝ws模塊,uuid模塊,ws是websocket模塊,uuid是為了生成唯一id的模塊

2.創建socketServer.js,引入相應模塊

let ws = require('ws');            //引入websocket模塊
let uuid = require('uuid');        //引入創建唯一id模塊

3.創建socket服務,創建客戶端連接數組

let socketServer = ws.Server;

let wss = new socketServer({port: 8090});    //創建websocketServer實例監聽8090端口

let clients = [];                //創建客戶端列表,用於保存客戶端及相關連接信息

4.創建廣播方法,用於向所有客戶端推送消息

/**
 * 廣播所有客戶端消息
 * @param  {String} type     廣播方式(admin為系統消息,user為用戶消息)
 * @param  {String} message  消息
 * @param  {String} nickname 用戶昵稱,廣播方式為admin時可以不存在
 */
function broadcastSend(type, message, nickname) {
    clients.forEach(function(v, i) {
        if(v.ws.readyState === ws.OPEN) {
            v.ws.send(JSON.stringify({
                "type": type,
                "nickname": nickname,
                "message": message
            }));
        }
    })
}

5.開始監聽端口以及數據

 

//監聽連接
wss.on('connection', function(ws) {
    let client_uuid = uuid.v4();
    let nickname = `AnonymousUser${clientIndex++}`;
    clients.push({
        "id": client_uuid,
        "ws": ws,
        "nickname": nickname
    });

    console.log(`client ${client_uuid} connected`);
    /**
     * 關閉服務,從客戶端監聽列表刪除
     */
    function closeSocket() {
        for(let i = 0; i < clients.length; i++) {
          if(clients[i].id == client_uuid) {
            let disconnect_message = `${nickname} has disconnected`;
            broadcastSend("notification", disconnect_message, nickname);
            clients.splice(i, 1);
          }
        }
    }
    /*監聽消息*/
    ws.on('message', function(message) {
        if(message.indexOf('/nick') === 0) {
            let nickname_array = message.split(' ');
            if(nickname_array.length >= 2) {
                let old_nickname = nickname;
                nickname = nickname_array[1];
                let nickname_message = `Client ${old_nickname} change to ${nickname}`;
                broadcastSend("nick_update", nickname_message, nickname);
            }
        } else {
            broadcastSend("message", message, nickname);
        }
    });
    /*監聽斷開連接*/
    ws.on('close', function() {
        closeSocket();
    })
})

客戶端

html:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <style>
        p {
            color: orange;
            padding: 5px 10px;
            margin: 0;
        }
        .user_msg {
            color: #ccc;
        }
        #messages {
            background: #000;
        }
    </style>
    <div class="vertical-center">
        <div class="container">
            <ul id="messages" class="list-unstyled"></ul>
            <hr/>
            <form role="form" id="chat_form" onsubmit="sendMessage(); return false;">
                <div class="form-group">
                    <input class="form-control" type="text" id="message" name="message"
                           placeholder="Type text to echo in here" value="" autofocus/>
                </div>
                <button type="button" id="send" class="btn btn-primary"
                        onclick="sendMessage();">
                    Send Message
                </button>

            </form>
            <div class="form-group"><span>nikename:</span><input id="name" type="text" /> <button class="btn btn-sm btn-info" onclick="changName();">change</button></div>
        </div>
    </div>

js:

    //建立連接
        var ws = new WebSocket("ws://localhost:8090");
        var nickname = "";
        ws.onopen = function (e) {
            console.log('Connection to server opened');
        }
        //顯示消息
        function appendLog(type, nickname, message) {
            if (typeof message == "undefined") return;
            var messages = document.getElementById('messages');
            var messageElem = document.createElement("li");
            var preface_label;
            var message_text;
            if (type === 'notification') {
                preface_label = `<span class="label label-warning"><i class="glyphicon glyphicon-plus"></i></span>`;
                message_text = `<p>${preface_label}&nbsp;&nbsp;${message}</p>`
            } else if (type == 'nick_update') {
                preface_label = `<span class="label label-warning"><i class="glyphicon glyphicon-bullhorn"></i></span>`;
                message_text = `<p>${preface_label}&nbsp;&nbsp;${message}</p>`
            } else {
                preface_label = `<span class="label label-info">${nickname}</span>`;
                message_text = `<p class="user_msg">${preface_label}&nbsp;&nbsp;${message}</p>`
            }
            messageElem.innerHTML = message_text;
            messages.appendChild(messageElem);
        }
        //收到消息處理
        ws.onmessage = function (e) {
            var data = JSON.parse(e.data);
            nickname = data.nickname;
            appendLog(data.type, data.nickname, data.message);
            console.log("ID: [%s] = %s", data.id, data.message);
        }
        //監聽連接關閉情況
        ws.onclose = function (e) {
            appendLog("Connection closed");
            console.log("Connection closed");
        }
        //發送消息
        function sendMessage() {
            var messageField = document.getElementById('message');
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(messageField.value);
            }
            messageField.value = '';
            messageField.focus();
        }
        //修改名稱
        function changName() {
            var name = $("#name").val();
            if (ws.readyState === WebSocket.OPEN) {
                ws.send("/nick " + name);
            }
        }

此時,我們的聊天室就已經完成了

websocket最主要的問題在於沒有內置的分組功能和廣播功能,需要程序員自己實現,理論上來說,構建好合適的分組結構,完全可以在網頁上實現qq的功能


免責聲明!

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



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