本次记录WebSocket接口是如何通过Node.js,如何发送与接收WebSocket的请求,由于前面已经准备好了Node.js的http模块的技术储备,所以在http模块的基础上准备WebSocket的网络请求,为后续的项目中会使用到的双向通信请求进行前期技术储备
WebSocket用于浏览器和服务端之间的双向通信,连接建立后,前端和Node.js服务端都可以主动发送消息
Node.js官方没有单独的WebSocket服务端模块,所以这里使用官方http模块接收升级请求,再使用官方crypto模块生成握手响应,只保留最基础的短文本消息接收与响应功能
ws发起->http->tcp->buffer->解析buffer中的stream流
const http = require("http");const crypto = require("crypto");const GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";let time = null;function send(socket, text) {const data = Buffer.from(text); socket.write(Buffer.concat([Buffer.from([0x81, data.length]), data]));}function read(buffer) {const length = buffer[1] & 0x7f;const mask = buffer.slice(2, 6);const data = buffer.slice(6, 6 + length);for (let i = 0; i < data.length; i++) { data[i] = data[i] ^ mask[i % 4]; }return data.toString();}const server = http.createServer((req, res) => { res.end("WebSocket服务端-运行中...");});server.on("upgrade", (req, socket) => {const key = req.headers["sec-websocket-key"];const accept = crypto .createHash("sha1") .update(key + GUID) .digest("base64"); socket.write( ["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${accept}`,"","", ].join("\r\n"), );console.log("有客户端已接入");let count = 0; time = setInterval(() => { count++;send(socket, "服务端消息主动推送-" + count);if (count > 10) {clearInterval(time); socket.end(); } }, 1000); socket.on("data", (buffer) => {if ((buffer[0] & 0x0f) === 0x8) { socket.end();return; }const message = read(buffer);console.log("收到客户端消息:(" + message + ")");send(socket, `回复客户端-服务端已收到-以下为收到的内容:${message}`); }); socket.on("close", () => {console.log("客户端已主动断开连接");clearInterval(time); }); socket.on("error", (err) => {clearInterval(time);console.error("WebSocket服务端连接异常:", err.message); });});server.listen(3000, () => {console.log("WebSocket 服务端已启动: ws://localhost:3000");});通过nodejs的服务调用另一个服务的WebSocket请求,这里先创建一个简单的HTTP服务,确保Node.js服务可以正常启动,然后在服务启动成功时,立即使用Node.js官方内置的WebSocket客户端连接指定的WebSocket接口地址
http->stream流->buffer缓冲区->tcp-发送成功
const http = require("http");const wsURL = "ws://localhost:3000"; // 替换为你要连接的WebSocket接口地址,当前地址为上方接收ws服务的地址function connectWebSocket() {const ws = new WebSocket(wsURL); ws.onopen = () => { ws.send("客户端主动推送: WebSocket连接成功");let time = null;let count = 0; time = setInterval(() => { count++; ws.send("客户端主动推送: 发送测试消息:" + count);if (count > 10) {clearInterval(time); ws.close(); } }, 1000); }; ws.onmessage = (event) => {console.log("收到服务端响应:", event.data); }; ws.onerror = (err) => {console.error("WebSocket请求失败:", err.message); }; ws.onclose = () => {console.log("WebSocket连接已关闭"); };}const server = http.createServer((req, res) => { res.writeHead(200, {"Content-Type": "text/plain; charset=utf-8", }); res.end("Node.js WebSocket客户端服务运行中");});server.listen(3001, () => { console.log("HTTP 服务已启动: http://localhost:3001"); connectWebSocket();});server.on("error", (err) => { console.error("HTTP服务启动失败: ", err.message);});ws://或wss://开头,wss://表示加密连接,就像http://与https://的区别WebSocket主要用于作为客户端发起连接,服务端仍然需要通过http的upgrade事件处理连接升级WebSocket,建议升级Node.js版本,本文不使用ws等外部依赖WebSocket的使用场景,不要滥用,就像轮询或定时器一样,不要滥用,必须要用则注意关闭或清理mkdir -p my-nodenpm init -ypackage.json,参考下方代码{"name":"my-node", "version":"1.0.0", "main":"main.js", "scripts":{"dev":"node main.js" }, "keywords":[], "author":"", "license":"ISC", "description":""}main.js 复制上方接收代码npm run dev启动postman或apifox这类可以主动发起各类请求的测试工具main.js与main-server.jsnode main-server.js,在启动main.js,在终端查看输出效果👉往期推荐:
NodeJS+Koa学习笔记(1-7)Node.js SSE请求接口开发
NodeJS+Koa学习笔记(1-6)Node.js Buffer 和 Stream的使用