You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express与Secure WebSocket(wss)端口冲突问题求助

解决Express与安全WebSocket(wss)共用同一端口的问题

核心问题分析

你代码里的关键错误是同时调用了server.listen()和app.listen(),这会启动两个完全独立的服务器:

  • server是带SSL证书的HTTPS服务器,同时承载wss服务
  • app.listen()会创建一个新的无SSL的HTTP服务器
    这两个服务器无法共用同一端口,直接导致了你遇到的“要么WebSocket失效、要么Express无响应”的冲突问题。

解决方案:仅启动HTTPS服务器

不需要双端口,完全可以共用同一端口。只需要移除app.listen(PORT)这一行,让承载了Express的HTTPS服务器来监听端口即可。因为你已经通过https.createServer({ key, cert }, app)把Express的请求处理逻辑绑定到了HTTPS服务器上,这个服务器会同时处理:

  • 常规的HTTPS请求(对应Express的路由接口)
  • WebSocket的升级请求(对应wss连接)

修正后的核心代码

const app = express()
const server = https.createServer({ key, cert }, app);  
const wss = new WebSocket.Server({ server})

// 配置wss连接逻辑
wss.on('connection', (ws, req) => {
    console.log('received socket connection ', req.headers['sec-websocket-key'])
    // ... 你的其他wss处理代码
})

// 只启动HTTPS服务器,共用同一端口
const PORT = process.env.PORT || 3002
server.listen(PORT);
console.log('Server is listening on port ' + PORT);

完整修正后的代码片段

const WebSocket = require('ws');
const fs = require('fs');

const https = require('https');
const express = require('express')
require('dotenv').config()
const keypath = process.env.environment=="production" ? process.env.key : 'localhost.key';
const certpath = process.env.environment=="production" ? process.env.cert : 'localhost.crt';
console.log("environment is ",process.env.environment)
const key = fs.readFileSync(keypath);
const cert = fs.readFileSync(certpath);
const bodyParser = require('body-parser')
const mongoose = require('mongoose')
const cors = require('cors')
const helmet = require('helmet')
const morgan = require('morgan')
const { MONGO_URI } = require('./config')
const worldRoutes = require('./src/routes/api/world_controller')
const environmentRoutes = require('./src/routes/api/environment_controller')
const worldObjectRoutes = require('./src/routes/api/worldObject_controller')
const interactionRoutes = require('./src/routes/api/interaction_controller')
const baseRoutes = require('./src/routes/api/base_controller') // 补充baseRoutes的引入

const app = express()

app.use(helmet())
app.use(bodyParser.json())
app.use(cors())
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'))
app.use(express.json())
mongoose
    .connect(process.env.MONGO_URI, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
    })
    .then(() => console.log('MongoDB connected!'))
    .catch((err) => console.log(err))

app.use('/api/world', worldRoutes)
app.use('/', baseRoutes)
const PORT = process.env.PORT || 3002

const server = https.createServer({ key, cert }, app);  
const wss = new WebSocket.Server({ server})
wss.on('connection', (ws, req) => {
    console.log('received socket connection ', req.headers['sec-websocket-key'])
    // ... 你的其他wss处理代码
})

// 移除app.listen(PORT),只启动HTTPS服务器
server.listen(PORT);
console.log('Server is listening on port ' + PORT);

// 注:原代码里的upgrade事件监听不需要手动添加,ws库会自动处理

额外说明

  • 你之前用非安全WebSocket(ws)时没问题,是因为当时应该是基于http.createServer(app)启动的单服务器,没有额外调用app.listen(),所以HTTP和ws可以共用端口。
  • 当使用wss时,必须依赖HTTPS服务器的SSL层,所以所有请求(包括Express接口和WebSocket连接)都要通过这个带证书的HTTPS服务器处理,不能再单独启动Express的HTTP服务器。

内容的提问来源于stack exchange,提问作者Daniel Shen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:25:46