为什么要有 WebSocket?
已经有了 HTTP 了为什么还要有 WebSocket 呢?
因为,HTTP 的请求只能由客户端发起,服务器接收。但是,现在想要让服务器端也可以主动发起请求。那么使用 HTTP 是无法满足的。
其次,还有一种就是,如果想要监听服务端发送的请求。那么,可以让客户端始终处于一种轮询状态。客户端每隔一段就发起一个询问,看一下服务端有没有请求信息。
使用轮询的缺点非常明显,流量一旦很大的话,后端服务的压力就很大。而且在高并发的情况下,很容易引起雪崩。例如,服务器端因为压力大导致在轮询的时候没有办法返回正常的响应,使得客户端进一步轮询等。综合使用 HTTP 的效率极其低下。
就在这样的场景下,工程师们经过不懈的思考,WebSocket由此诞生。
WebSocket 的特点&场景
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,设计用于在客户端(通常是浏览器)和服务器之间建立持久连接,以实现实时数据传输。
1. 实时通信
优点:
- 低延迟:WebSocket 连接一旦建立,客户端和服务器之间可以立即传输数据,无需每次都进行 HTTP 请求和响应,从而减少延迟。
- 双向通信:WebSocket 支持全双工通信,客户端和服务器可以同时发送和接收数据,适合实时应用。
使用场景:
- 实时聊天应用:如 Slack、WhatsApp Web 版。
- 在线游戏:需要快速、实时的数据交换。
- 金融交易平台:如股票交易、外汇交易,需要快速获取市场数据和执行交易。
2. 持久连接
优点:
- 减少带宽消耗:由于 WebSocket 连接是持久的,避免了 HTTP 请求的头部开销,特别是在频繁通信的场景下,可以显著减少带宽消耗。
- 状态保持:持久连接使得客户端和服务器可以保持状态,不需要每次请求都重新建立连接和身份验证。
使用场景:
- 物联网(IoT)设备:需要持续监控和控制设备状态。
- 协作工具:如 Google Docs,实现多个用户实时编辑同一文档。
3. 简化开发
优点:
- 标准化协议:WebSocket 是一种标准化协议,浏览器和服务器端库普遍支持,简化了开发和集成。
- 统一接口:WebSocket API 提供了一个统一的接口,用于建立连接、发送和接收消息,简化了开发过程。
使用场景:
- 实时通知系统:如网站的即时通知、消息推送。
- 实时数据流:如实时数据分析和可视化仪表盘。
4. 更高效的资源使用
优点:
- 服务器资源优化:WebSocket 持久连接减少了服务器需要处理的连接建立和关闭的开销。
- 客户端资源优化:客户端不需要频繁发起新的连接请求,减少了资源消耗。
使用场景:
- 社交媒体:如 Twitter 的实时更新流。
- 在线协作工具:如 Trello 的实时看板更新。
5. 替代轮询和长轮询
优点:
- 减少不必要的请求:传统的轮询和长轮询需要客户端频繁向服务器发送请求以检查新数据,浪费网络带宽和服务器资源。WebSocket 通过持久连接避免了这种情况。
- 更好的用户体验:实时更新和低延迟通信为用户提供了更好的互动体验。
使用场景:
- 实时数据更新应用:如天气预报、股票市场数据。
- 在线协作和会议:如视频会议、实时文档编辑。
WebSocket 的建立的过程
WebSocket的初始化过程非常简单,可以理解为是在 HTTP 基础上进行了协商之后,将 HTTP 协议升级成了 WebSocket 协议。

1. 建立连接(握手)
WebSocket 连接始于客户端向服务器发送一个 HTTP 请求,以启动 WebSocket 握手过程。
客户端请求
客户端发送一个 HTTP GET 请求,其中包含一些特定的头部字段来表示请求升级到 WebSocket 协议。以下是一个典型的握手请求示例:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Upgrade: websocket: 表示请求将协议升级为 WebSocket。Connection: Upgrade: 表示连接需要升级。Sec-WebSocket-Key: 一个随机生成的 Base64 编码的密钥,用于服务器生成响应密钥。Sec-WebSocket-Version: WebSocket 协议的版本,当前常用的是 13。
服务器响应
服务器接收到握手请求后,生成一个响应,并确认协议升级。以下是一个典型的握手响应示例:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
101 Switching Protocols: 表示协议切换成功。Upgrade: websocket: 确认升级到 WebSocket 协议。Connection: Upgrade: 确认连接升级。Sec-WebSocket-Accept: 服务器通过对Sec-WebSocket-Key进行 SHA-1 哈希并 Base64 编码生成的值。
一旦握手成功,HTTP 连接将升级为 WebSocket 连接,并且可以开始进行数据传输。
2. 数据传输
在 WebSocket 连接建立后,客户端和服务器可以通过这个连接进行全双工(双向)数据传输。数据通过帧(frame)进行传输。
发送消息
客户端和服务器都可以发送文本帧或二进制帧。例如,发送一个文本消息:
(这里我们先使用 javascrip)
// 客户端
const socket = new WebSocket('ws://example.com/chat');
socket.onopen = function(event) {
socket.send('Hello Server!');
};
// 服务器(使用 Node.js WebSocket 库)
const WebSocket = require('ws');
const wss = new WebSocket.Server({
port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
ws.send('Hello Client!');
});
});
接收消息
客户端和服务器都可以接收消息:
// 客户端
socket.onmessage = function(event) {
console.log('Message from server: ', event.data);
};
// 服务器
ws.on('message', function incoming(message) {
console.log('Message from client: ', message);
});
3. 关闭连接
WebSocket 连接可以由客户端或服务器任意一方关闭。关闭连接的过程包括发送一个关闭帧。
WebSocket 的报文

WebSocket 是一种全双工、双向通信协议,允许客户端和服务器之间进行实时数据交换。WebSocket 的报文结构在设计上非常高效,具有较小的开销。
WebSocket 帧结构
WebSocket 数据通过帧(frame)进行传输,每个帧由以下几个部分组成:
- FIN, RSV1, RSV2, RSV3 和 Opcode(第1个字节)
- Mask 和 Payload Length(第2个字节)
- 扩展的 Payload Length(可选)(第3-10个字节)
- Masking Key(可选)(第4-14个字节)
- Payload Data(有效负载数据)(第5-14个字节之后)
1. FIN, RSV1, RSV2, RSV3 和 Opcode
- FIN (1 bit):表示这是消息的最后一个帧。如果是最后一个帧,FIN 为 1;否则为 0。
- RSV1, RSV2, RSV3 (1 bit each):保留位,通常为 0,除非定义了扩展。
- Opcode (4 bits):表示帧的类型。常见的 Opcode 值:
0x0:继续帧(Continuation frame)0x1
Go语言中WebSocket的快速入门指南

最低0.47元/天 解锁文章
3278

被折叠的 条评论
为什么被折叠?



