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