计算机网络基础知识-WebSocket

0 阅读9分钟

WebSocket 协议概述

WebSocket 是 HTML5 提供的一种浏览器与服务器进行全双工通讯的网络技术,属于应用层协议,基于 RFC 6455 标准。

核心工作机制

WebSocket 基于 TCP 传输协议,并复用 HTTP 的握手通道。浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

WebSocket 的出现解决了半双工通信的弊端,其最大特点是:服务器可以向客户端主动推送消息,客户端也可以主动向服务器推送消息。

WebSocket 原理

客户端向 WebSocket 服务器通知一个带有所有接收者 ID 的事件,服务器接收后立即通知所有活跃的客户端,只有 ID 在接收者 ID 序列中的客户端才会处理这个事件。

WebSocket 核心特性

  1. 支持双向通信,实时性更强:客户端和服务器可以同时发送和接收数据。
  2. 可以发送文本,也可以发送二进制数据:支持多种数据类型传输。
  3. 建立在 TCP 协议之上,服务端的实现比较容易:基于成熟的 TCP 协议栈。
  4. 数据格式比较轻量,性能开销小,通信高效:最小头部仅 2 字节,传输效率高。
  5. 没有同源限制,客户端可以与任意服务器通信:跨域通信能力(需服务器允许)。
  6. 协议标识符是 ws(如果加密,则为 wss),服务器网址就是 URL:统一的 URL 标识方案。
  7. 与 HTTP 协议有着良好的兼容性:默认端口也是 80/443,握手阶段使用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。

WebSocket 握手过程

客户端请求

WebSocket 握手基于 HTTP 协议升级机制,客户端发送升级请求:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13

服务器响应

服务器验证请求后返回协议切换响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Sec-WebSocket-Accept 的生成算法为:base64(sha1(Sec-WebSocket-Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

WebSocket 数据帧格式

WebSocket 协议的核心是轻量级的数据帧格式:

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-------+-+-------------+
|F|R|R|R| opcode|M| Payload Len |
|I|S|S|S|  (4)  |A|     (7)     |
|N|V|V|V|       |S|             |
| |1|2|3|       |K|             |
+-+-+-+-+-------+-+-------------+

关键字段说明

  • FIN(1bit):标识是否为消息的最后一帧
  • Opcode(4bit):帧类型标识
    • 0x0:延续帧(分片消息的中间帧)
    • 0x1:文本帧(UTF-8编码)
    • 0x2:二进制帧
    • 0x8:关闭连接帧
    • 0x9:Ping帧(心跳检测)
    • 0xA:Pong帧(心跳响应)
  • Mask(1bit):是否使用掩码(客户端到服务器必须为1)
  • Payload Len:数据负载长度

WebSocket 心跳机制

为了保持连接活跃,WebSocket 协议定义了 Ping/Pong 帧用于心跳检测:

// 服务器定时发送心跳
setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
        ws.ping('heartbeat');
    }
}, 25000);

// 客户端自动回复
ws.on('pong', (data) => {
    console.log('连接状态正常');
});

推荐的心跳间隔为 25-30 秒,避免与常见的网络超时设置冲突。

WebSocket 客户端实现

基本使用

// 创建WebSocket连接
const ws = new WebSocket('wss://api.example.com/chat');

// 连接建立事件
ws.onopen = (event) => {
    console.log('WebSocket连接已建立');
    ws.send(JSON.stringify({type: 'join', room: 'general'}));
};

// 消息接收事件
ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    console.log('收到消息:', data);
};

// 错误处理
ws.onerror = (error) => {
    console.error('连接错误:', error);
};

// 连接关闭事件
ws.onclose = (event) => {
    console.log(`连接关闭: ${event.code} - ${event.reason}`);
};

连接状态管理

WebSocket 连接有4种状态:

  • CONNECTING(0):连接正在建立
  • OPEN(1):连接已建立,可以通信
  • CLOSING(2):连接正在关闭
  • CLOSED(3):连接已关闭

即时通讯技术对比分析

短轮询(Short Polling)

基本思路:浏览器每隔一段时间向服务器发送 HTTP 请求,服务器在收到请求后,不论是否有数据更新,都直接进行响应。

工作机制:这种方式实现的即时通信,本质上还是浏览器发送请求、服务器接受请求的一个过程,通过让客户端不断地进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。

优点:实现简单,易于理解,兼容性最好。

缺点:由于需要不断的建立 HTTP 连接,严重浪费了客户端和服务器端的资源。当用户增加时,服务器端的压力就会变大。

长轮询(Long Polling)

基本思路:首先由客户端向服务器发起请求,当服务器收到客户端发来的请求后不会直接进行响应,而是先将这个请求挂起,然后判断数据是否有更新。如果有更新,则进行响应;如果一直没有数据,则到达一定的时间限制才返回。客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。

优点:长轮询和短轮询比起来,明显减少了很多不必要的 HTTP 请求次数,相比之下节约了资源。

缺点:连接挂起也会导致资源的浪费。

服务器发送事件(SSE)

基本思路:服务器使用流信息向客户端推送信息。严格地说,HTTP 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息。也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。SSE 就是利用这种机制,使用流信息向客户端推送信息。

优点:SSE 相对于前面两种方式来说,不需要建立过多的 HTTP 请求,相比之下节约了资源。

限制:SSE 基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。SSE 是单向通信的,只能由服务器向客户端推送信息,如果客户端需要发送信息就是属于下一个 HTTP 请求了。

WebSocket

基本思路:WebSocket 是 HTML5 定义的一个新协议,与传统的 HTTP 协议不同,该协议允许由服务器主动向客户端推送信息。WebSocket 是一个全双工的协议,也就是通信双方是平等的,可以相互发送消息。

优点:真正的实时双向通信,延迟最低,性能最优。

缺点:在服务器端的配置比较复杂,兼容性相对较差。

四种通信协议深度对比

协议基础对比

对比维度短轮询长轮询SSEWebSocket
协议基础HTTPHTTPHTTPTCP
通信方式客户端主动查询服务器挂起响应服务器单向推送全双工双向
连接建立每次请求新建每次请求新建一次连接持久一次握手持久
数据流向双向(请求-响应)双向(请求-响应)单向(服务器→客户端)双向同时

性能对比分析

性能指标短轮询长轮询SSEWebSocket
实时性低(取决于轮询间隔)中(服务器有数据立即响应)高(服务器主动推送)最高(真正实时)
带宽效率低(大量无效请求)中(减少无效请求)高(流式传输)最高(轻量级帧)
服务器负载高(频繁建立连接)中(连接挂起消耗)低(持久连接)最低(一次连接)
客户端资源高(频繁请求)中(连接管理复杂)低(自动处理)最低(事件驱动)

兼容性与适用场景

方案浏览器兼容性适用场景不适用场景
短轮询完美兼容所有浏览器兼容性要求极高、数据更新频率低高频实时通信
长轮询很好兼容中等实时性要求、无法使用 WebSocket需要真正实时双向通信
SSE良好(除IE/Edge)服务器向客户端单向推送、新闻推送、监控需要客户端主动发送数据
WebSocket良好(现代浏览器)聊天、游戏、实时交易、高频数据交换兼容性要求极高、服务器不支持

选择依据总结

选择 WebSocket,当

  • 需要真正的实时双向通信
  • 数据交换频率高(每秒多次)
  • 对延迟敏感的应用
  • 需要传输二进制数据

选择其他方案,当

  • 兼容性要求极高 → 短轮询
  • 服务器环境不支持 WebSocket → 长轮询
  • 只需要服务器向客户端的单向推送 → SSE

技术选型指南

从性能的角度来看:WebSocket > 长连接(SSE) > 长轮询 > 短轮询

如果考虑浏览器的兼容性问题:短轮询 > 长轮询 > 长连接(SSE) > WebSocket

要根据具体的使用场景来判断使用哪种方式

  • 对于实时性要求极高的场景(如在线游戏、金融交易),优先选择 WebSocket
  • 对于只需要服务器推送的场景(如新闻推送、监控),SSE 是更好的选择
  • 在兼容性要求极高的环境中,短轮询或长轮询是必要的备选方案

总结

WebSocket 协议通过一次握手建立持久连接,实现了真正的全双工实时通信。其轻量级的数据帧格式和内置的心跳机制,使其在高频数据交换场景中具有显著优势。

在实际应用中,需要根据具体的业务需求、性能要求和兼容性约束选择最合适的实时通信方案。WebSocket 特别适合需要低延迟、高频双向通信的场景,而其他方案在特定场景下也有各自的优势。

通过深入理解各种通信协议的特点和适用场景,可以做出更合理的技术选型决策,为用户提供优质的实时交互体验。