4、ws库入门:安装ws库、创建WebSocket服务器、处理连接事件、发送与接收消息

好,咱们开始动手了。

前面聊了那么多WebSocket的理论,说白了,它就是个协议。真正要干活,还得靠具体的库。Node.js生态里,ws库是当之无愧的老大哥。我这些年做实时通信项目,十有八九用的都是它。为什么?轻量、稳定、API设计得干净利落。

这一章,咱们就把ws库装好,然后亲手搭一个WebSocket服务器出来。你想想看,从零到一,也就十几行代码的事。

4.1 安装ws库

安装这事,没什么技术含量。但有个小细节,我建议你注意一下。

打开终端,进到你的项目目录,然后执行:

npm install ws

嗯,就这么简单。装完之后,你可以在package.json里看到它。

我的习惯:我个人习惯把 ws 装到 dependencies 里,而不是 devDependencies。因为它是运行时依赖,不是开发工具。虽然装错地方也能用,但部署的时候容易出幺蛾子。

如果你用的是 yarn 或者 pnpm,命令也差不多:

yarn add ws
# 或者
pnpm add ws

装好之后,咱们验证一下。在项目里新建一个 test.js,写一行:

const WebSocket = require('ws');
console.log('ws 库加载成功,版本:', WebSocket);

跑一下 node test.js,没报错就说明成了。

4.2 创建WebSocket服务器

好,库装好了。接下来咱们创建一个真正的WebSocket服务器。

新建一个文件,叫 server.js。然后写下面这段代码:

const WebSocket = require('ws');

const wss = new WebSocket.Server({
  port: 8080
});

console.log('WebSocket 服务器已启动,监听端口 8080');

就这么几行,一个WebSocket服务器就跑起来了。你可以在终端执行 node server.js,然后看到那句日志。

注意:端口号别跟其他服务冲突。我遇到过好几次,端口被占了,服务器起不来,还以为是代码写错了。检查一下 8080 有没有被占用,或者换个端口试试。

当然,你也可以指定主机地址。比如只允许本地连接:

const wss = new WebSocket.Server({
  host: '127.0.0.1',
  port: 8080
});

我个人习惯在开发阶段用 0.0.0.0,这样局域网里其他设备也能连上来测试。但生产环境一定要绑内网IP,别暴露到公网去。

4.3 处理连接事件

服务器搭好了,但它现在啥也不干。你得告诉它:当有客户端连上来的时候,该做什么。

WebSocket服务器最核心的事件就是 connection。每当一个新客户端连上来,就会触发这个事件。

wss.on('connection', function(ws) {
  console.log('有新的客户端连接了');

  // 这里 ws 就是当前连接的客户端对象
  // 你可以用它来收发消息
});

你看,代码很直观。wss.on('connection', callback),回调函数里的 ws 参数,就代表这个新连接。

除了 connection,还有几个常用事件:

事件名 触发时机 说明
connection 新客户端连接成功 最常用,拿到 ws 对象
close 连接关闭 可以在这里做清理工作
error 发生错误 一定要监听,否则会抛异常
headers 收到客户端HTTP头 可以用来做鉴权
我曾经踩过的坑:刚开始用 ws 的时候,我忘了监听 error 事件。结果客户端异常断开时,服务器直接崩溃了。后来我养成了习惯——所有事件都至少加个空监听,尤其是 error

4.4 发送与接收消息

连接建立好了,接下来就是真正的通信了。说白了,就是两件事:发消息和收消息。

4.4.1 接收消息

客户端发来的消息,通过 ws.on('message') 来接收:

wss.on('connection', function(ws) {
  ws.on('message', function(data) {
    console.log('收到消息:', data.toString());
  });
});

注意,data 默认是一个 Buffer 对象。所以你需要调用 .toString() 转成字符串。当然,你也可以设置 wsbinaryType 来改变数据类型。

4.4.2 发送消息

发送消息就更简单了,直接调用 ws.send()

ws.send('你好,客户端!');

也可以发送JSON数据。我建议你养成习惯,所有结构化数据都用JSON格式传输:

const message = {
  type: 'greeting',
  content: '你好,客户端!',
  timestamp: Date.now()
};

ws.send(JSON.stringify(message));

为什么?因为这样客户端解析起来方便,而且容易扩展。我在项目中见过有人用自定义分隔符拼字符串,后来需求一变,改得想哭。

4.4.3 完整的示例

把上面这些串起来,一个完整的服务器大概长这样:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function(ws) {
  console.log('新客户端已连接');

  // 发送欢迎消息
  ws.send(JSON.stringify({
    type: 'system',
    content: '欢迎连接到WebSocket服务器'
  }));

  // 接收消息
  ws.on('message', function(data) {
    console.log('收到:', data.toString());

    // 回复客户端
    ws.send('服务器已收到你的消息:' + data.toString());
  });

  // 处理断开
  ws.on('close', function() {
    console.log('客户端已断开连接');
  });

  // 处理错误
  ws.on('error', function(err) {
    console.error('连接出错:', err);
  });
});

console.log('WebSocket 服务器已启动');
小技巧:你可以用 ws.readyState 来判断连接状态。它的值有四种:CONNECTING (0)、OPEN (1)、CLOSING (2)、CLOSED (3)。发送消息前检查一下,能避免很多莫名其妙的错误。

4.5 测试一下

服务器写好了,怎么测?你可以用浏览器自带的WebSocket API来测。打开浏览器控制台,输入:

const ws = new WebSocket('ws://localhost:8080');

ws.onopen = function() {
  console.log('连接成功');
  ws.send('你好,服务器!');
};

ws.onmessage = function(event) {
  console.log('收到服务器消息:', event.data);
};

看到控制台里来回的消息了吗?嗯,这就是实时通信的感觉。

当然,你也可以用一些在线工具来测试。但我个人建议,刚开始学的时候,用浏览器控制台就够了。简单直接,不用装额外的东西。

4.6 本章小结

这一章咱们干了三件事:

  • 安装了 ws
  • 创建了一个WebSocket服务器
  • 实现了消息的收发

你想想看,从零到能跑通一个实时通信服务,也就十几行代码。WebSocket的门槛其实很低,难的是后面的架构设计、性能优化、断线重连这些实战问题。

下一章,咱们会深入聊聊如何管理多个客户端连接,以及如何实现广播功能。到时候,你就可以做一个简单的聊天室了。

课后练习:试着修改上面的代码,让服务器收到消息后,自动加上时间戳再返回给客户端。这个小练习能帮你巩固 message 事件和 send 方法的使用。