IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> nodejs中,实现HTTP协议和WS协议复用同一端口 -> 正文阅读

[网络协议]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 = 8001

app.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

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:37:35  更:2021-09-13 09:38:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年9日历 -2024/9/21 6:54:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码