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:UpgradeUpgrade:websocket,向服务器请求修改协议为websocket,如果服务器同意修改协议,则会响应一个响应码为101的HTTP报文,至此HTTP的职责已经完成,下面的通讯则会采用websocket协议。(注意:只有在客户端使用实例化的websocket实例传输数据才会采用websocket协议,在此期间客户端仍可以发起其他的http请求,两者并不冲突)。

​ 由此可得,只需让http服务处理所有的请求,在遇到Connection:UpgradeUpgrade:websocket时换用websocket服务即可,此时只需http监听端口,而websocket不必对外监听,而由http服务直接转发。

​ 下面给出采用expresshttpws模块实现"复用"端口的代码:

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://localhostws://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/chatws://localhost/file,而其他的URI则无法建立连接。

​ 采用这种方式则可以在连接前做其他的事情,如用户身份验证

03、参考链接&&API

ws

express

http

nodejs中,实现HTTP协议和WS协议复用同一端口相关推荐

  1. nginx websocket wss 连接失败 failed_浅谈WebSocket协议、WS协议和WSS协议原理及关系

    现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...

  2. php reactphp wss_浅谈WebSocket协议、WS协议和WSS协议原理及关系

    websocket在实时通信领域运用的比较多,比如社交聊天.弹幕.多玩家游戏.协同编辑.股票基金实时报价.体育实况更新.视频会议/聊天.基于位置的应用.在线教育.智能家居等需要高实时的场景. 具体到w ...

  3. 浅谈WebSocket协议、WS协议和WSS协议原理及关系

    现如今,一些游戏,网站,APP,支付行业的网络经常会收到DDOS和CC,因此这个事情也变得不足为奇了.但在防护方案中有多种不同的方案.如,今天有几个同事在针对高防CDN问题讨论的时,谈到WebSock ...

  4. php-ews发送邮件,node.js 基于 STMP 协议和 EWS 协议发送邮件

    本文主要介绍 node.js 发送基于 STMP 协议和 MS Exchange Web Service(EWS) 协议的邮件的方法.文中所有参考代码均以 TypeScript 编码示例. 1 基于 ...

  5. Bytom BIP-32协议和BIP-44协议解读

    我们知道HD(分层确定性)钱包,基于 BIP-32:多币种和多帐户钱包,基于 BIP-44:最近比原社区的钱包开发者对比原的BIP-32和BIP-44协议有疑问,所以我今天就专门整理了一下该协议的内容 ...

  6. RabbitMQ MQTT协议和AMQP协议

    RabbitMQ MQTT协议和AMQP协议 1        序言... 1 1.1     RabbitMq结构... 1 1.2     RabbitMq消息接收... 4 1.3     Ex ...

  7. fx5u mc协议_SLMP协议和MC协议

    一.概述 SLMP(Seamless Message Protocol)是在以太网中使用的协议.MC协议则包含了串口以及以太网的通信协议,范围更广. SLMP的3E帧或4E帧(3)的报文格式与MC协议 ...

  8. 485通讯协议_HART协议和RS485协议有什么区别?

    HART协议和RS485协议的区别如下: 1.概念不同 HART协议是采用基于Bell202标准的FSK频移键控信号,在低频的4-20mA模拟信号上叠加幅度为0.5mA的音频数字信号进行双向数字通讯: ...

  9. STM8单片机串口同时识别自定义协议和Modbus协议

      在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通.   在实际开发过程中由 ...

最新文章

  1. 掏空老底,值得推荐的10个学习神器,总有一个用得上!
  2. ES6 中 Promise 详解
  3. 浏览器复制不进行url编码_谷歌浏览器测试版支持在PC上复制号码并操作关联安卓设备进行拨打...
  4. 影视感悟专题---1、B站-魔兽世界代理及其它乱七八糟
  5. 鸿蒙os系统被推送,鸿蒙来了!华为大规模推送鸿蒙OS系统,造成网站一度瘫痪...
  6. [剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表]
  7. [UE4] Sequence 的某一条分支执行 delay 之后会继续执行下一条分支而不是停留在该分支
  8. php语言开始和结束分别为,0055 PHP语言简介和HelloWorld
  9. ISP DSP的不同
  10. 【答题卡识别】基于matlab Hough变换答题卡识别【含Matlab源码 250期】
  11. 【模糊综合评价原理与案例】
  12. GHOST怎么用(转)
  13. BigGAN代码解读(gpt3.5的帮助)——谱正则化部分
  14. 【java】java中输出字符串中的单个字符及获得其长度
  15. 使用kd树数据结构,实现k-means聚类加速
  16. CSS flex-direction用法解释
  17. 联想拯救者连不上网?
  18. 《C++ 黑客编程揭秘与防范(第2版)》——6.8 KeyMake工具的使用
  19. 块存储,文件存储,对象存储的区别和理解
  20. 佟强——对外经济贸易大学信息学院

热门文章

  1. 2023年天津农学院专升本专业课考试具体安排及准考证打印时间
  2. 删除重复导入的手机照片
  3. DuiLib实现仿微信聊天界面
  4. 2017 CCPC- 杭州站总结!
  5. STL之sstream的用法
  6. 单例模式中懒汉式和饿汉式实现
  7. 【机器视觉3】双目立体视觉模型
  8. SwiftUI———如何使用Core Image官方滤镜(CIFilter)来处理照片
  9. ARP攻击与SYN攻击
  10. AVProVideo☀️六、Unity播放PC端和安卓端视频、以及对视频的读写方法