nodejs中,实现HTTP协议和WS协议复用同一端口
00、前言
最近在写一个网页,需要用到后端的websocket服务,由于不需要太复杂的功能,后端选择使用nodejs的nodejs-websocket
模块。在开发过程中发现还需要http服务,但nodejs-websocket
无法实现http服务,于是便开始寻求可以解决两个协议共用同一端口的方法。
01、有关问题
一般来说,每个服务启动时都需占用一个端口。例如上面所提到的nodejs-websocket
,如下代码所示(代码来源:nodejs-websocket
):
const ws = require("nodejs-websocket")const server = ws.createServer(function (conn) {console.log("New connection")conn.on("text", function (str) {console.log("Received "+str)conn.sendText(str.toUpperCase()+"!!!")})conn.on("close", function (code, reason) {console.log("Connection closed")})
}).listen(8001)
运行以上代码开启了一个websocket服务,监听8001
端口。
如果这时再运行一个http服务,如express
,同样监听8001
端口就会出现端口冲突,如以下代码(代码来源:express
中文网):
const express = require('express')
const app = express()
const port = 8001app.get('/', (req, res) => {res.send('Hello World!')
})app.listen(port, () => {console.log(`Example app listening at http://localhost:${port}`)
})
将上述两个服务同时运行,则会出现:Error: listen EADDRINUSE: address already in use :::8001
错误提示。
如果你不太明白端口的意义或者用途,可以参考计算机网络相关书籍。简要来说,端口在计算机通讯中用以标记一个服务或应用,以便传输层知道将某数据包具体给应用层的哪个应用。
以上启动了两个服务,而这两个服务又是独立的,且同时监听了同一端口,此时就会出现端口冲突的情况。
02、如何实现复用端口
在客户端发起websocket连接时,客户端会向浏览器发送一个http请求,该请求的请求头包含Connection:Upgrade
和Upgrade:websocket
,向服务器请求修改协议为websocket,如果服务器同意修改协议,则会响应一个响应码为101的HTTP报文,至此HTTP的职责已经完成,下面的通讯则会采用websocket协议。(注意:只有在客户端使用实例化的websocket实例传输数据才会采用websocket协议,在此期间客户端仍可以发起其他的http请求,两者并不冲突)。
由此可得,只需让http服务处理所有的请求,在遇到Connection:Upgrade
和Upgrade:websocket
时换用websocket服务即可,此时只需http监听端口,而websocket不必对外监听,而由http服务直接转发。
下面给出采用express
、http
、ws
模块实现"复用"端口的代码:
const express = require("express");
const WS_MODULE = require("ws");
const http = require("http");const app = express();
const port = 80;app.get("/hello", (req, res) => {res.send("hello world");
});const server = http.createServer(app);
ws = new WS_MODULE.Server({ server });ws.on("connection", (conn) => {conn.on("message", (str) => {//handle received message});
});server.listen(port, () => {console.log("服务器已开启,端口号:" + port);
});
以上代码中,该应用可同时提供websocket和http服务,且域名下任何的请求路径在切换协议为websocket时都是一样的处理方式。即:在这种情况下连接ws://localhost
和ws://localhost/walekj/awe/dacz
没有任何区别。
如果想对不同的websocket请求路径采用不同的websocket服务,可以使用以下代码:
const express = require("express");
const WS_MODULE = require("ws");
const http = require("http");const app = express();
const port = 80;app.get("/hello", (req, res) => {res.send("hello world");
});const server = http.createServer(app);const chatWS = new WS_MODULE.Server({ noServer: true }); //这里采用noServer
chatWS.on("connection", (conn) => {console.log("新的客户端连接 chatWS进行处理");
});const fileWS = new WS_MODULE.Server({ noServer: true }); //这里采用noServer
fileWS.on("connection", (conn) => {console.log("新的客户端连接 fileWS进行处理");
});server.on("upgrade", (req, socket, head) => {if (req.url === "/chat") {//由chatWS 进行处理chatWS.handleUpgrade(req, socket, head, (conn) => {chatWS.emit("connection", conn, req);});} else if (req.url === "/file") {//由fileWS 进行处理fileWS.handleUpgrade(req, socket, head, (conn) => {fileWS.emit("connection", conn, req);});} else {//直接关闭连接socket.destroy();}
});server.listen(port, () => {console.log("服务器已开启,端口号:" + port);
});
现在可以连接ws://localhost/chat
和ws://localhost/file
,而其他的URI则无法建立连接。
采用这种方式则可以在连接前做其他的事情,如用户身份验证
03、参考链接&&API
ws
express
http
nodejs中,实现HTTP协议和WS协议复用同一端口相关推荐
- nginx websocket wss 连接失败 failed_浅谈WebSocket协议、WS协议和WSS协议原理及关系
现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...
- php reactphp wss_浅谈WebSocket协议、WS协议和WSS协议原理及关系
websocket在实时通信领域运用的比较多,比如社交聊天.弹幕.多玩家游戏.协同编辑.股票基金实时报价.体育实况更新.视频会议/聊天.基于位置的应用.在线教育.智能家居等需要高实时的场景. 具体到w ...
- 浅谈WebSocket协议、WS协议和WSS协议原理及关系
现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...
- php-ews发送邮件,node.js 基于 STMP 协议和 EWS 协议发送邮件
本文主要介绍 node.js 发送基于 STMP 协议和 MS Exchange Web Service(EWS) 协议的邮件的方法.文中所有参考代码均以 TypeScript 编码示例. 1 基于 ...
- Bytom BIP-32协议和BIP-44协议解读
我们知道HD(分层确定性)钱包,基于 BIP-32:多币种和多帐户钱包,基于 BIP-44:最近比原社区的钱包开发者对比原的BIP-32和BIP-44协议有疑问,所以我今天就专门整理了一下该协议的内容 ...
- RabbitMQ MQTT协议和AMQP协议
RabbitMQ MQTT协议和AMQP协议 1 序言... 1 1.1 RabbitMq结构... 1 1.2 RabbitMq消息接收... 4 1.3 Ex ...
- fx5u mc协议_SLMP协议和MC协议
一.概述 SLMP(Seamless Message Protocol)是在以太网中使用的协议.MC协议则包含了串口以及以太网的通信协议,范围更广. SLMP的3E帧或4E帧(3)的报文格式与MC协议 ...
- 485通讯协议_HART协议和RS485协议有什么区别?
HART协议和RS485协议的区别如下: 1.概念不同 HART协议是采用基于Bell202标准的FSK频移键控信号,在低频的4-20mA模拟信号上叠加幅度为0.5mA的音频数字信号进行双向数字通讯: ...
- STM8单片机串口同时识别自定义协议和Modbus协议
在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通. 在实际开发过程中由 ...
最新文章
- 掏空老底,值得推荐的10个学习神器,总有一个用得上!
- ES6 中 Promise 详解
- 浏览器复制不进行url编码_谷歌浏览器测试版支持在PC上复制号码并操作关联安卓设备进行拨打...
- 影视感悟专题---1、B站-魔兽世界代理及其它乱七八糟
- 鸿蒙os系统被推送,鸿蒙来了!华为大规模推送鸿蒙OS系统,造成网站一度瘫痪...
- [剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表]
- [UE4] Sequence 的某一条分支执行 delay 之后会继续执行下一条分支而不是停留在该分支
- php语言开始和结束分别为,0055 PHP语言简介和HelloWorld
- ISP DSP的不同
- 【答题卡识别】基于matlab Hough变换答题卡识别【含Matlab源码 250期】
- 【模糊综合评价原理与案例】
- GHOST怎么用(转)
- BigGAN代码解读(gpt3.5的帮助)——谱正则化部分
- 【java】java中输出字符串中的单个字符及获得其长度
- 使用kd树数据结构,实现k-means聚类加速
- CSS flex-direction用法解释
- 联想拯救者连不上网?
- 《C++ 黑客编程揭秘与防范(第2版)》——6.8 KeyMake工具的使用
- 块存储,文件存储,对象存储的区别和理解
- 佟强——对外经济贸易大学信息学院