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的功能

原文地址:https://www.cnblogs.com/timmer/p/6520628.html