关于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} ${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} ${message}</p>` } else { preface_label = `<span class="label label-info">${nickname}</span>`; message_text = `<p class="user_msg">${preface_label} ${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的功能