代码存档
https://stackblitz.com/edit/stackblitz-starters-k8v48a?file=readme.md
icedog.websocket-test: websocket测试练习
tool.js
tool.js
/**
* 获取 id 创建器
* @returns
*/
const getIdCreator = () => {
let clientIdx = 0;
return () => {
clientIdx += 1;
return clientIdx;
}
};
/**
* 定义一个函数 fillZero,用于将数字转换为指定长度的字符串,不足长度时在前面补零
* @param {number} num - 要处理的数字
* @param {number} targetLength - 目标字符串的长度,默认为 2
* @returns {string} 返回补零后的字符串
*/
const fillZero = (num, targetLength = 2) => {
// 将数字转换为字符串
let numText = num.toString();
// 计算需要补零的数量
let zeroCount = targetLength - numText.length;
// 初始化用于存储补零后的字符串
let data = "";
// 循环添加零
for (let i = 0; i < zeroCount; i++) {
data += "0";
}
// 将原始数字字符串添加到补零后的字符串后面
data += numText;
// 返回最终结果
return data;
}
/**
* 获取当前时间字符串
* @returns
*/
const getDateNowText = () => {
let date = new Date();
let year = date.getFullYear();
let month = fillZero(date.getMonth() + 1);
let day = fillZero(date.getDate());
let hour = fillZero(date.getHours());
let minute = fillZero(date.getMinutes());
let second = fillZero(date.getSeconds());
let millisecond = fillZero(date.getMilliseconds(), 3);
return `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}`;
}
/**
* 延迟函数
* @param {number} ms
* @returns
*/
const delay = (ms) =>
new Promise((resolve) => {
setTimeout(() => {
resolve(ms);
}, ms);
});
module.exports = { delay, getDateNowText, getIdCreator };
ws 单个客户端和单个服务端通信文本数据示例
ws 单个客户端和单个服务端通信文本数据示例,详情看代码
server.js
const { WebSocketServer } = require('ws');
const tool = require('../tools/tool');
/**
* 概念:
* ws服务器:WebSocketServer
* ws 实例:WebSocket
*/
/**
* 创建发送文本消息的 ws 服务端
*/
const createWSTextServer = () => {
let dataIdx = 1;
/**
* 创建 ws 服务器实例
*/
const webSocketServer = new WebSocketServer({ port: 3000 });
webSocketServer.on('connection', (webSocket, request) => {
console.log(`[${tool.getDateNowText()}] 接收到一个新的 ws 链接`);
/**
* 每当一个客户端 ws 实例创建,ws 服务器会创建一个和ws客户端对应的ws服务端实例进行通讯
*/
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}] ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('message', (bufferData,isBinary) => {
let data = bufferData.toString();
console.log(`[${tool.getDateNowText()}] 收到 WebSocket 客户端消息:${data}`);
let dataJson = JSON.parse(data);
dataJson.fromServer = true;
console.log(`[${tool.getDateNowText()}] 向客户端发送消息`);
webSocket.send(JSON.stringify(dataJson));
// if (dataIdx > 3) {
// console.log(`[${tool.getDateNowText()}] 和客户端通讯了 3 次,关闭通讯`);
// webSocket.close(3002,'server close');
// }
// dataIdx++;
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 服务端关闭,code:${code},reason:${reason}`);
});
});
console.log(`[${tool.getDateNowText()}] ws 服务器启动成功`);
}
createWSTextServer();
client.js
const { WebSocket } = require('ws');
const tool = require('../tools/tool');
/**
* 创建发送文本消息的 ws 客户端
*/
const createWSTextClient = () => {
let dataIdx = 1;
const wsUrl = 'ws://localhost:3000';
const webSocket = new WebSocket(wsUrl);
/**
* 发送消息到服务端
*/
const sendMessage = () => {
let data = {
type: "client",
data: dataIdx,
fromServer: false,
}
dataIdx++;
webSocket.send(JSON.stringify(data));
}
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}]ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('open', () => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端开启`);
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
sendMessage();
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端关闭,code:${code},reason:${reason}`);
});
webSocket.on('message', (bufferData, isBinary) => {
let data = bufferData.toString();
console.log(`[${tool.getDateNowText()}] 收到WebSocket 服务端消息:${data}`);
if (dataIdx > 3) {
console.log(`[${tool.getDateNowText()}] 和服务端通讯了 3 次,关闭通讯`);
webSocket.close(3001,"client close");
}
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
setTimeout(() => {
sendMessage();
}, 100);
});
console.log(`[${tool.getDateNowText()}] ws 客户端启动成功`);
}
createWSTextClient();
ws 单个客户端和单个服务端通信二进制数据示例
ws 单个客户端和单个服务端通信二进制数据示例,详情看代码
server.js
const { WebSocketServer } = require('ws');
const tool = require('../tools/tool');
/**
* 概念:
* ws服务器:WebSocketServer
* ws 实例:WebSocket
*/
/**
* 创建发送二进制消息的 ws 服务端
*/
const createWSBinaryServer = () => {
let dataIdx = 1;
/**
* 创建 ws 服务器实例
*/
const webSocketServer = new WebSocketServer({ port: 3000 });
const processBufferDataToInt32Array = (bufferData) => {
let int32numArr = [];
for (let i = 0; i < bufferData.length; i += 4) {
let n = bufferData.readInt32LE(i);
int32numArr.push(n);
}
let int32data = new Int32Array(int32numArr);
return int32data;
}
webSocketServer.on('connection', (webSocket, request) => {
console.log(`[${tool.getDateNowText()}] 接收到一个新的 ws 链接`);
/**
* 每当一个客户端 ws 实例创建,ws 服务器会创建一个和ws客户端对应的ws服务端实例进行通讯
*/
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}] ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('message', (bufferData, isBinary) => {
let int32Arr=processBufferDataToInt32Array(bufferData);
let data = int32Arr.toString();
console.log(`[${tool.getDateNowText()}] 收到 WebSocket 客户端消息:${data},isBinary:${isBinary}`);
console.log(`[${tool.getDateNowText()}] 向客户端发送消息`);
let sendData = new Int32Array(3);
sendData[0] = 999;
sendData[1] = 666;
sendData[2] = 999;
webSocket.send(sendData);
// if (dataIdx > 3) {
// console.log(`[${tool.getDateNowText()}] 和客户端通讯了 3 次,关闭通讯`);
// webSocket.close(3002,'server close');
// }
// dataIdx++;
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 服务端关闭,code:${code},reason:${reason}`);
});
});
console.log(`[${tool.getDateNowText()}] ws 服务器启动成功`);
}
createWSBinaryServer();
client.js
const { WebSocket } = require('ws');
const tool = require('../tools/tool');
/**
* 创建发送二进制消息的 ws 客户端
*/
const createWSBinaryClient = () => {
let dataIdx = 1;
const wsUrl = 'ws://localhost:3000';
const webSocket = new WebSocket(wsUrl);
const processBufferDataToInt32Array = (bufferData) => {
let int32numArr = [];
for (let i = 0; i < bufferData.length; i += 4) {
let n = bufferData.readInt32LE(i);
int32numArr.push(n);
}
let int32data = new Int32Array(int32numArr);
return int32data;
}
/**
* 发送消息到服务端
*/
const sendMessage = () => {
let data = new Int32Array(10);
for (let i = 0; i < data.length; i++) {
data[i] = i + 5000;
}
dataIdx++;
webSocket.send(data);
}
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}]ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('open', () => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端开启`);
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
sendMessage();
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端关闭,code:${code},reason:${reason}`);
});
webSocket.on('message', (bufferData, isBinary) => {
let int32Arr=processBufferDataToInt32Array(bufferData);
let data = int32Arr.toString();
console.log(`[${tool.getDateNowText()}] 收到WebSocket 服务端消息:${data},isBinary:${isBinary}`);
if (dataIdx > 3) {
console.log(`[${tool.getDateNowText()}] 和服务端通讯了 3 次,关闭通讯`);
webSocket.close(3001, "client close");
}
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
setTimeout(() => {
sendMessage();
}, 100);
});
console.log(`[${tool.getDateNowText()}] ws 客户端启动成功`);
}
createWSBinaryClient();
ws 多个客户端和单个服务端通信文本数据示例
server.js
const { WebSocketServer } = require('ws');
const tool = require('../tools/tool');
/**
* 概念:
* ws服务器:WebSocketServer
* ws 实例:WebSocket
*/
/**
* 创建发送文本消息的 ws 服务端
*/
const createWSTextServer = () => {
let dataIdx = 1;
/**
* 创建 ws 服务器实例
*/
const webSocketServer = new WebSocketServer({ port: 3000 });
webSocketServer.on('connection', (webSocket, request) => {
console.log(`[${tool.getDateNowText()}] 接收到一个新的 ws 链接`);
/**
* 每当一个客户端 ws 实例创建,ws 服务器会创建一个和ws客户端对应的ws服务端实例进行通讯
*/
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}] ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('message', (bufferData,isBinary) => {
let data = bufferData.toString();
console.log(`[${tool.getDateNowText()}] 收到 WebSocket 客户端消息:${data}`);
let dataJson = JSON.parse(data);
dataJson.fromServer = true;
console.log(`[${tool.getDateNowText()}] 向客户端发送消息`);
webSocket.send(JSON.stringify(dataJson));
// if (dataIdx > 3) {
// console.log(`[${tool.getDateNowText()}] 和客户端通讯了 3 次,关闭通讯`);
// webSocket.close(3002,'server close');
// }
// dataIdx++;
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 服务端关闭,code:${code},reason:${reason}`);
});
});
console.log(`[${tool.getDateNowText()}] ws 服务器启动成功`);
}
createWSTextServer();
client.js
const { WebSocket } = require('ws');
const tool = require('../tools/tool');
/**
* 创建发送文本消息的 ws 客户端
*/
const createWSTextClient = (clientId) => {
let dataIdx = 1;
const wsUrl = 'ws://localhost:3000';
const webSocket = new WebSocket(wsUrl);
/**
* 发送消息到服务端
*/
const sendMessage = () => {
let data = {
type: "client",
data: dataIdx,
fromServer: false,
clientId:clientId,
}
dataIdx++;
webSocket.send(JSON.stringify(data));
}
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}]ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('open', () => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端开启`);
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
sendMessage();
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端关闭,code:${code},reason:${reason}`);
});
webSocket.on('message', (bufferData, isBinary) => {
let data = bufferData.toString();
console.log(`[${tool.getDateNowText()}] 收到WebSocket 服务端消息:${data}`);
if (dataIdx > 3) {
console.log(`[${tool.getDateNowText()}] 和服务端通讯了 3 次,关闭通讯`);
webSocket.close(3001, "client close");
}
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
setTimeout(() => {
sendMessage();
}, 100);
});
console.log(`[${tool.getDateNowText()}] ws 客户端启动成功`);
}
const createClientList = (clientCount) => {
for (let i = 1; i <= clientCount; i++) {
createWSTextClient(i);
}
}
createClientList(10)
ws 服务 和 http 服务集成,并且和网页进行文字通信
前端采用最新的esm模式写法
server.js
const { WebSocketServer } = require('ws');
const http = require('http');
const fs = require('fs');
const path = require('path');
const tool = require('../tools/tool');
/**
* 概念:
* ws服务器:WebSocketServer
* ws 实例:WebSocket
*/
/**
* 创建http 服务集成 ws 服务端
*/
const createHttpServerWithWSServer = () => {
const mineTypeDict = {
".js": "application/javascript",
".mjs": "application/javascript",
".html": "text.html",
".css": "text/css",
};
const httpServer = http.createServer((req, res) => {
let fileNameSegment = "";
if (req.url == "/") {
fileNameSegment = ["index.html"];
} else {
fileNameSegment = req.url.substring(1).split("/");
}
// 定义HTML文件的路径
const filePath = path.join(__dirname, 'public', ...fileNameSegment);
let extName = path.extname(filePath);
let contentType=mineTypeDict[extName];
// 设置响应头,指定内容类型和编码
res.setHeader('Server','icedog');
res.setHeader('Content-Type', contentType);
// 读取HTML文件内容并返回
fs.readFile(filePath, (err, data) => {
if (err) {
// 如果发生错误,返回500状态码和错误信息
res.writeHead(500);
res.end(`Error: ${err.message}`);
} else {
// 否则,返回200状态码和HTML内容
res.writeHead(200);
res.end(data);
}
});
})
/**
* 创建 ws 服务器实例
*/
const webSocketServer = new WebSocketServer({ server: httpServer });
// const webSocketServer = new WebSocketServer({ noServer: true });// 不绑定 httpserver 前端ws就会报错
webSocketServer.on('connection', (webSocket, request) => {
console.log(`[${tool.getDateNowText()}] 接收到一个新的 ws 链接`);
/**
* 每当一个客户端 ws 实例创建,ws 服务器会创建一个和ws客户端对应的ws服务端实例进行通讯
*/
webSocket.on('error', (error) => {
console.error(`[${tool.getDateNowText()}] ws 通讯发生了错误,错误信息`, error)
});
webSocket.on('message', (bufferData, isBinary) => {
let data = bufferData.toString();
console.log(`[${tool.getDateNowText()}] 收到 WebSocket 客户端消息:${data}`);
let dataJson = JSON.parse(data);
dataJson.fromServer = true;
console.log(`[${tool.getDateNowText()}] 向客户端发送消息`);
webSocket.send(JSON.stringify(dataJson));
});
webSocket.on('close', (code, reason) => {
console.log(`[${tool.getDateNowText()}] WebSocket 服务端关闭,code:${code},reason:${reason}`);
});
});
httpServer.listen(3000, () => {
console.log(`[${tool.getDateNowText()}] http 服务和ws 服务启动成功\n - http 访问地址:http://localhost:3000 \n - ws 访问地址:ws://localhost:3000 `);
});
}
createHttpServerWithWSServer();
public/js/index.mjs
import tool from 'js/tool';
/**
* 创建发送文本消息的 ws 客户端
*/
const createWSClient = () => {
let dataIdx = 1;
const wsUrl = 'ws://localhost:3000';
const webSocket = new WebSocket(wsUrl);
/**
* 发送消息到服务端
*/
const sendMessage = () => {
let data = {
type: "client",
data: dataIdx,
fromServer: false,
}
dataIdx++;
webSocket.send(JSON.stringify(data));
}
webSocket.addEventListener('error', (event) => {
console.error(`[${tool.getDateNowText()}]ws 通讯发生了错误,错误信息`, event)
});
webSocket.addEventListener('open', (event) => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端开启`);
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
sendMessage();
});
webSocket.addEventListener('close', (event) => {
console.log(`[${tool.getDateNowText()}] WebSocket 客户端关闭,code:${event.code},reason:${event.reason}`);
});
webSocket.addEventListener('message', (event) => {
let data = event.data;
console.log(`[${tool.getDateNowText()}] 收到WebSocket 服务端消息:${data}`);
if (dataIdx > 3) {
console.log(`[${tool.getDateNowText()}] 和服务端通讯了 3 次,关闭通讯`);
webSocket.close(3001,"client close");
return;
}
console.log(`[${tool.getDateNowText()}] 向服务端发送消息`);
setTimeout(() => {
sendMessage();
}, 100);
});
console.log(`[${tool.getDateNowText()}] ws 客户端启动成功`);
}
createWSClient();
public/js/tool.mjs
/**
* 获取 id 创建器
* @returns
*/
const getIdCreator = () => {
let clientIdx = 0;
return () => {
clientIdx += 1;
return clientIdx;
}
};
/**
* 填充 0
* @param {number} num
* @param {number} targetLength
*/
const fillZero = (num, targetLength = 2) => {
let numText = num.toString();
let zeroCount = targetLength - numText.length;
let data = "";
for (let i = 0; i < zeroCount; i++) {
data += "0";
}
data += numText;
return data;
}
/**
* 获取当前时间字符串
* @returns
*/
const getDateNowText = () => {
let date = new Date();
let year = date.getFullYear();
let month = fillZero(date.getMonth() + 1);
let day = fillZero(date.getDate());
let hour = fillZero(date.getHours());
let minute = fillZero(date.getMinutes());
let second = fillZero(date.getSeconds());
let millisecond = fillZero(date.getMilliseconds(), 3);
return `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}`;
}
/**
* 延迟函数
* @param {number} ms
* @returns
*/
const delay = (ms) =>
new Promise((resolve) => {
setTimeout(() => {
resolve(ms);
}, ms);
});
export default { delay, getDateNowText, getIdCreator };
public/css/index.mjs
html,body{
background-color: aquamarine;
}
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ws 服务 和 http 服务集成测试</title>
<link href="./css/index.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="app">
<div class="title">ws 服务 和 http 服务集成测试</div>
<div class="desc">请按 F12 查看控制台</div>
</div>
<script type="importmap">
{
"imports": {
"js/tool":"./js/tool.mjs"
}
}
</script>
<script src="js/index.mjs" type="module"></script>
</body>
</html>
发表评论