搭建第一个 WebSocket 服务器:使用 ws 库创建 WebSocket 服务器、监听连接与消息事件
好,咱们开始动手了。
信令服务器说白了就是一个中间人,帮两个浏览器互相递话。WebSocket 是目前最常用的递话方式。我最早做 WebRTC 项目时,第一件事就是搭这个 WebSocket 服务器。那时候踩了不少坑,今天我把最稳的路径告诉你。
为什么选 ws 库?
Node.js 生态里 WebSocket 库不少,比如 socket.io、ws、uWebSockets.js。我个人习惯用 ws,原因很简单:
- 轻量——没有多余的回退机制,就是纯 WebSocket
- 稳定——npm 周下载量几千万,社区验证过
- API 简洁——你花 10 分钟就能上手
socket.io 虽然自带房间和自动重连,但它的协议不是标准 WebSocket。如果你后面要对接其他客户端(比如 iOS、Android),ws 更干净。
初始化项目
先建一个文件夹,然后初始化 npm 项目:
mkdir webrtc-signaling-server
cd webrtc-signaling-server
npm init -y
接着安装 ws:
npm install ws
嗯,就这一步。没有其他依赖。
创建 WebSocket 服务器
新建一个 server.js,写下面这段代码:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
console.log('WebSocket 服务器已启动,监听端口 8080');
就这么几行,一个 WebSocket 服务器就跑起来了。你运行 node server.js,控制台会打印出启动信息。
监听连接事件
服务器建好了,但还没处理任何连接。我们需要监听 connection 事件:
wss.on('connection', function connection(ws, req) {
console.log('新客户端连接,IP:', req.socket.remoteAddress);
});
这里的 ws 是当前连接的实例,req 是 HTTP 请求对象。你可以通过 req 拿到客户端的 IP、URL 参数等信息。
为什么会需要 IP?我在做信令服务器时,经常用它做简单的访问控制——比如只允许内网 IP 连接。
监听消息事件
连接建立后,客户端会发消息过来。我们监听 message 事件:
ws.on('message', function incoming(message) {
console.log('收到消息:', message.toString());
});
注意 message 默认是 Buffer 类型,需要转成字符串。如果你确定客户端只发文本,也可以直接 message.toString()。
实际项目中,消息通常是 JSON 格式。我会这样处理:
ws.on('message', function incoming(data) {
try {
const parsed = JSON.parse(data);
console.log('收到 JSON 消息:', parsed);
} catch (e) {
console.error('消息格式错误:', data.toString());
}
});
嗯,这里要注意:信令消息必须是结构化的。如果客户端发来乱码,直接抛异常会断开连接。我习惯用 try-catch 包一层,至少让服务器不崩溃。
完整代码示例
把上面几段拼起来,就是一个可用的信令服务器雏形:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, req) {
console.log('新客户端连接,IP:', req.socket.remoteAddress);
ws.on('message', function incoming(data) {
try {
const message = JSON.parse(data);
console.log('收到消息:', message);
// 这里后面会加信令处理逻辑
// 比如转发 offer、answer、ICE 候选
} catch (e) {
console.error('消息解析失败:', data.toString());
}
});
ws.on('close', function close() {
console.log('客户端断开连接');
});
ws.on('error', function error(err) {
console.error('连接错误:', err);
});
});
console.log('WebSocket 信令服务器已启动,端口 8080');
你想想看,这个服务器现在能做什么?
- 接受 WebSocket 连接
- 接收 JSON 消息
- 打印日志
- 处理断开和错误
说白了,骨架已经搭好了。后面我们只需要往 message 处理里填信令逻辑就行。
测试服务器
你可以用浏览器控制台测试:
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
ws.send(JSON.stringify({ type: 'ping' }));
};
ws.onmessage = (e) => {
console.log('收到:', e.data);
};
打开浏览器 F12,粘贴这段代码。如果控制台没有报错,说明连接成功。
核心逻辑流程图
下面这张图展示了 WebSocket 信令服务器的核心工作流程:
常见问题与避坑
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 连接被拒绝 | 端口被占用或防火墙拦截 | 换端口或检查防火墙规则 |
| 消息收不到 | 客户端发送的是二进制数据 | 服务端用 message.toString() 转换 |
| 连接频繁断开 | 心跳机制缺失 | 后面章节会讲如何实现心跳 |
| JSON 解析报错 | 客户端发送了非 JSON 格式 | 用 try-catch 包裹解析逻辑 |
小结
今天我们做了三件事:
- 用 ws 库创建了一个 WebSocket 服务器
- 监听了 connection 事件,拿到每个客户端连接
- 监听了 message 事件,处理 JSON 格式的信令消息
这个服务器虽然简单,但已经是信令服务器的核心骨架。后面所有的信令逻辑——房间管理、消息转发、ICE 候选交换——都是在这个基础上加功能。
你可以在本地跑起来试试。打开两个浏览器标签页,都连上这个服务器,然后互相发消息。能通,就说明你迈出了第一步。