1. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
2.示例代码
前端
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>WebSocketTest</title> <script type="text/javascript"> var ws; if ("WebSocket" in window) { console.log("您的浏览器支持 WebSocket!"); ws = new WebSocket("ws://localhost:8090"); ws.onopen = function () { ws.send("发送数据"); console.log("数据发送中..."); }; ws.onmessage = function (evt) { var received_msg = evt.data; console.log("数据已接收:", received_msg); }; ws.onclose = function () { console.log("连接已关闭..."); }; ws.onerror = function (err) { console.log("error...",err); }; } else { console.log("您的浏览器不支持 WebSocket!"); } function WebSocketTest() { if(ws.close){ ws.close(); } } </script> </head> <body> <div id="sse"> <a href="javascript:WebSocketTest()">关闭 WebSocket</a> </div> </body> </html>
前端 + node : 聊天室
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <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> </head> <body> <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> <script> var nickname = ""; var ws = new WebSocket("ws://localhost:8090"); ws.onopen = function (e) { console.log('Connection to server opened'); } 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 changName() { var name = $("#name").value; if (ws.readyState === WebSocket.OPEN) { ws.send("/nick " + name); } } 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); } function sendMessage() { var messageField = document.getElementById('message'); if (ws.readyState === WebSocket.OPEN) { ws.send(messageField.value); } messageField.value = ''; messageField.focus(); } function $(s) { return document.querySelector(s) } // ajax({ // url:'https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg', // method:'get', // async:true, // success:function(data){ // console.log('success',data); // }, // error:function(data){ // console.log('error',data); // } // }) // function ajax(opt) { // opt = opt || {}; // opt.url = opt.url || ''; // opt.data = opt.data || null; // opt.success = opt.success || function () {}; // opt.method = (function (method) { // if (method) { // return method.toUpperCase() == 'GET' ? 'GET' : 'POST'; // }; // return 'GET'; // }(opt.method)); // opt.async = (function (async) { // return (!async ||async +'' == 'false') ? false : true; // }(opt.async)); // var xmlHttp = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); // var postData = (function (data) { // var params = []; // for (var key in data) { // params.push(key + '=' + data[key]); // } // return params.join('&'); // }(opt.data)); // if (opt.method === 'POST') { // xmlHttp.open(opt.method, opt.url, opt.async); // xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'); // xmlHttp.send(postData); // } else if (opt.method === 'GET') { // xmlHttp.open(opt.method, opt.url + '?t=' + Math.random() + '&' + postData, opt.async); // xmlHttp.send(null); // } // xmlHttp.onreadystatechange = function () { // if (xmlHttp.readyState == 4) { // if (xmlHttp.status == 200) { // opt.success(xmlHttp.responseText); // } else { // opt.error(xmlHttp.status); // } // } // }; // } </script> </body> </html>
node
npm install uuid ws --save
let ws = require('ws');
let uuid = require('uuid');
let socketServer = ws.Server;
let wss = new socketServer({port: 8090});
let clients = [];
let clientIndex = 0;
function broadcastSend(type, message, name) {
clients.forEach(function(v, i) {
if(v.ws.readyState === ws.OPEN) {
v.ws.send(JSON.stringify({
"type": type,
"name": name,
"message": message
}));
}
})
}
//监听连接
wss.on('connection', function(ws) {
let client_uuid = uuid.v4();
let name = `AnonymousUser${clientIndex++}`;
clients.push({
"id": client_uuid,
"ws": ws,
"name": name
});
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 = `${name} has disconnected`;
broadcastSend("notification", disconnect_message, name);
clients.splice(i, 1);
}
}
}
/*监听消息*/
ws.on('message', function(message) {
if(message.indexOf('/nick') === 0) {
let name_array = message.split(' ');
if(name_array.length >= 2) {
let old_name = name;
name = name_array[1];
let name_message = `Client ${old_name} change to ${name}`;
broadcastSend("nick_update", name_message, name);
}
} else {
broadcastSend("message", message, name);
}
});
/*监听断开连接*/
ws.on('close', function() {
closeSocket();
})
})