前言
在实时通信场景(聊天、协同编辑、行情数据)里,我们经常会看到 ws:// 与 wss:// 两种协议前缀。很多同学知道它们和 WebSocket 有关,却不一定清楚到底差别在哪、与 HTTP/HTTPS 有什么关系。本篇文章将延续《博客搭建一-项目工程搭建》那种“原理 + 步骤 + 示例”的讲解方式,带你彻底搞懂 ws 与 wss。
一、WebSocket 协议回顾
1.1 解决了什么问题?
- HTTP 天生是 请求-响应 模式,客户端必须主动拉取。
- 某些业务需要 服务器主动推送 数据,例如消息提醒、看板更新。
- WebSocket 通过一次握手升级,将 HTTP 连接变成 全双工 通道,允许双方随时发送数据。
1.2 握手关键点
- 浏览器发起 HTTP 请求,并在 Header 中附带:
Upgrade: websocketConnection: UpgradeSec-WebSocket-Key
- 服务器验证并返回
Sec-WebSocket-Accept。 - 双方切换到 WebSocket 帧格式持续通信。
这个握手阶段决定了我们使用 ws:// 还是 wss://。
二、ws 与 wss 的区别
| 协议 | 传输层 | 默认端口 | 对应关系 |
|---|---|---|---|
ws:// |
TCP(明文) | 80 | 类似 HTTP |
wss:// |
TLS over TCP(加密) | 443 | 类似 HTTPS |
- ws:未加密,适用于内网或对安全要求不高的场景。
- wss:在 ws 之上加入 TLS(SSL),所有帧都被加密,浏览器也会执行证书验证,适合公开站点或涉及敏感数据的业务。
注意:现代浏览器在 HTTPS 页面中 禁止 创建
ws://连接,必须使用wss://,否则会报 Mixed Content。
三、URL 结构与示例
ws://example.com:8080/path?token=abc
wss://realtime.webfem.com/quote
- 协议前缀:ws / wss
- 主机:域名或 IP
- 端口:默认 80 / 443,可自定义
- 路径与查询参数:用于区分业务、传递凭证
四、Node.js 服务端实战
使用 ws 库快速启动一个既支持 ws 又支持 wss 的服务:
import http from 'node:http';
import https from 'node:https';
import fs from 'node:fs';
import {
WebSocketServer } from 'ws';
const server = http.createServer();
const secureServer = https.createServer({
cert: fs.readFileSync('./ssl/fullchain.pem'),
key: fs.readFileSync('./ssl/privkey.pem'),
});
const wss = new WebSocketServer({
server });
const wssSecure = new WebSocketServer({
server: secureServer });
const handleConnection = (socket) => {
socket.on('message', (msg) => {
console.log('来自客户端:', msg.toString());
socket.send(`服务端已收到:${
Date.now()}`);
});
};
wss.on('connection', handleConnection);
wssSecure.on('connection', handleConnection);
server.listen(8080, () => console.log('ws://localhost:8080'));
secureServer.listen(8443, () => console.log('wss://localhost:8443'));
ws://localhost:8080未加密wss://localhost:8443需要证书,可以使用自签名证书测试
五、调试
const socket = new WebSocket('wss://realtime.webfem.com/quote');
socket.addEventListener('open', () => {
console.log('已连接');
socket.send(JSON.stringify({
type: 'subscribe', symbol: 'BTCUSDT' }));
});
socket.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
console.log('最新行情', data);
});
socket.addEventListener('close', () => console.log('连接关闭'));
socket.addEventListener('error', (err) => console.error('异常', err));
只需要把 URL 改成 ws:// 或 wss:// 即可切换,API 完全一致。
也可以直接使用在想工具WebSocket在线测试工具,快速测试。
六、安全性与部署建议
- HTTPS 页面统一使用 wss,避免浏览器拦截。
- 若后端在同一台服务器,可利用 Nginx 反向代理,统一 443 端口,将 TLS 解密交由 Nginx 完成:
location /socket {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
- 认证:通过查询参数、Cookie、JWT 或自定义协议字段,在握手阶段校验身份。
- 心跳/断线重连:客户端定期发送 ping/pong 或心跳包,配合指数退避的重连策略。
七、常见排障清单
Error during WebSocket handshake: Unexpected response code: 404- 检查服务器是否正确处理
/socket路径。
- 检查服务器是否正确处理
Mixed Content: The page at https://... was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint ws://...- 使用
wss://或在本地 HTTP 页面调试。
- 使用
- 证书错误(NET::ERR_CERT_AUTHORITY_INVALID)
- 在正式环境使用由可信 CA 签发的证书,或在开发环境信任自签名证书。
总结
- ws 对应 HTTP,wss 对应 HTTPS,功能一致但安全性不同。
- 现代浏览器在 HTTPS 页面强制使用 wss。
- 服务端只需在 Transport 层加上 TLS 就能提供 wss,Nginx 反代是主流做法。
- 构建实时应用时,提前规划认证、心跳与重连策略,才能让 WebSocket 链接稳定可靠。
掌握 ws 与 wss 的差异和使用场景,你就能自如地在任何业务中接入 WebSocket,实现真正实时的产品体验。