Skip to content
/ Communication/WebSocket
9/17/2024
3.3m
AI 摘要

本文介绍了 WebSocket 的基本概念和在 NodeJs 中的搭建方法,重点讲解了 WS over HTTP 的实现方式,通过不同请求路径区分多个 WS 服务,实现单端口多服务,提升部署灵活性和效率。

WebSocket

WebSocket 是一种双向实时通信协议,允许客户端和服务器建立持久连接,以实时传递消息和数据

搭建 WS 服务

NodeJs 中,可以使用 websockets/ws 搭建 WebSocket 服务端

$ npm i ws

通过上面的代码,通过搭建 WebSocket 服务,实现了服务端和客户端的通信,这非常不错

但是代入实际场景中,我们会发现另一个问题,在我们已有的 HTTP 服务上添加 webSocket 服务似乎似乎有一些弊端:比如需要开启额外端口,对于开放防火墙端口和代理都不友好

WS over HTTP

但是代入实际场景中,我们会发现另一个问题,在我们已有的 HTTP 服务上添加 webSocket 服务似乎似乎有一些弊端:比如需要开启额外端口,对于开放防火墙端口和代理都不友好

WS 是基于 HTTP 的,所以实际上我们有更好的方式,就是 WebSocket over HTTP。这种行为允许在相同的端口上同时提供 HTTP 和 WebSocket 服务

比如我们留两个 HTTP 接口 __api_1__、__api_2__,用于连接不同的 WS 服务:

比如我们留两个 HTTP 接口 __api_1__、__api_2__,用于连接不同的 WS 服务:

import { WebSocketServer}  from 'ws'
import { createServer } from 'http'

const server = createServer()
const wss1 = new WebSocketServer({ noServer: true })
const wss2 = new WebSocketServer({ noServer: true })

wss1.on('connection', (ws) => {
    //...
})
wss2.on('connection', (ws) => {
    //...
})

// 有 WS 请求来的时候,upgrade 被触发
server.on('upgrade', (req, socket, head) => {
    const { pathname } = new URL(req.url || '/', 'http://localhost')
    // 当请求路径是 __api_1__ 的时候,升级为 ws 服务,让 wss1 去处理
    if(pathname === '/__api_1__') {
        wss1.handleUpgrade(req, socket, head, ws => {
            wss.emit('connection', ws, req)
        })
    // 当请求路径是 __api_2__ 的时候,升级为 ws 服务,让 wss2 去处理
    } else if(pathname === '/__api_2__') {
        wss2.handleUpgrade(req, socket, head, ws => {
            wss.emit('connection', ws, req)
        })
    }
})

server.listen(3000)

对应的客户端代码只需要加一个路径即可

参考 Vite 当中,对于 HMR 服务的实现,也是采用类似上面的方式:

Released under the MIT License.