websocket的工作原理

WebSocket 是一种在 Web 应用程序中实现全双工通信的协议。它允许客户端和服务器之间建立一个持久的连接,双方可以在这个连接上相互发送数据,而不需要通过传统的 HTTP 请求/响应模式。这使得 WebSocket 特别适用于实时应用,如聊天应用、在线游戏、实时数据推送等。以下是 WebSocket 的工作原理的详细说明。

WebSocket 的工作原理

1. 建立连接

WebSocket 连接的建立从一个 HTTP 请求开始。客户端通过一个 HTTP 请求(通常称为 "握手" 请求)请求升级协议,从 HTTP 升级到 WebSocket。

客户端请求:

复制代码

http复制代码

GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com

  • Upgrade: websocketConnection: Upgrade 标头表示客户端请求升级到 WebSocket 协议。
  • Sec-WebSocket-Key 是一个 Base64 编码的随机密钥,用于安全验证。

服务器响应:

复制代码

http复制代码

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

  • 状态码 101 Switching Protocols 表示服务器同意协议升级。
  • Sec-WebSocket-Accept 是服务器基于 Sec-WebSocket-Key 计算的一个值,确保握手请求的合法性。
2. 数据传输

一旦连接建立,客户端和服务器之间的通信使用 WebSocket 帧(frame)。WebSocket 帧有不同的类型,包括文本帧、二进制帧、关闭帧、Ping 帧和 Pong 帧。

  • 文本帧(Text Frame):用于传输文本数据(UTF-8 编码字符串)。
  • 二进制帧(Binary Frame):用于传输二进制数据。
  • 关闭帧(Close Frame):用于关闭连接。
  • Ping 帧和 Pong 帧:用于连接的心跳检测,维持连接的活跃状态。

每个 WebSocket 帧都有一个固定的头部格式,用于控制帧的类型和传输的负载数据。

3. 关闭连接

WebSocket 连接可以由客户端或服务器任意一方关闭。关闭连接的过程通过发送一个关闭帧来实现,另一方收到关闭帧后会响应一个关闭帧并关闭连接。

复制代码

http复制代码

// 客户端或服务器发送关闭帧 0x88 0x00

关闭帧的第一个字节 0x88 表示帧的类型为关闭帧,第二个字节 0x00 表示负载长度为 0。

WebSocket 的优点

  1. 全双工通信:客户端和服务器可以在同一个连接上同时发送和接收消息,减少延迟。
  2. 持久连接:连接一旦建立,可以持续存在,避免了 HTTP 请求/响应的开销。
  3. 减少带宽消耗:由于减少了 HTTP 头部的开销,WebSocket 比传统的轮询和长轮询更高效。

WebSocket 的使用

客户端代码示例(JavaScript)
复制代码

javascript复制代码

// 创建 WebSocket 连接 var socket = new WebSocket("ws://example.com/socket"); // 连接打开事件 socket.onopen = function(event) { console.log("WebSocket is open now."); // 发送数据 socket.send("Hello Server!"); }; // 接收消息事件 socket.onmessage = function(event) { console.log("Received message from server:", event.data); }; // 连接关闭事件 socket.onclose = function(event) { console.log("WebSocket is closed now."); }; // 连接错误事件 socket.onerror = function(error) { console.log("WebSocket error:", error); };

服务器代码示例(Node.js + ws 库)
复制代码

javascript复制代码

const WebSocket = require('ws'); // 创建 WebSocket 服务器 const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', function connection(ws) { console.log('A new client connected'); // 接收消息事件 ws.on('message', function incoming(message) { console.log('Received message:', message); // 发送消息给客户端 ws.send('Hello from server'); }); // 连接关闭事件 ws.on('close', function close() { console.log('Client disconnected'); }); });

WebSocket 协议的详细解析

WebSocket 帧格式

WebSocket 帧头部格式如下:

复制代码

复制代码

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-------+-+-------------+-------------------------------+ |F|R|R|R| opcode|M| Payload len | Extended payload length | |I|S|S|S| (4) |A| (7) | (16/64) | |N|V|V|V| |S| | (if payload len==126/127) | | |1|2|3| |K| | | +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + | Extended payload length continued, if payload len == 127 | + - - - - - - - - - - - - - - - +-------------------------------+ | |Masking-key, if MASK set to 1 | +-------------------------------+-------------------------------+ | Masking-key (continued) | Payload Data | +-------------------------------- - - - - - - - - - - - - - - - + : Payload Data continued ... : + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Payload Data continued ... | +---------------------------------------------------------------+

  • FIN (1 bit): 表示是否是消息的最后一帧。
  • RSV1, RSV2, RSV3 (1 bit each): 保留位,通常为 0。
  • Opcode (4 bits): 表示帧的类型(如文本帧、二进制帧、关闭帧等)。
  • MASK (1 bit): 表示是否掩码(客户端发送给服务器的数据必须使用掩码)。
  • Payload len (7 bits) : 表示负载数据的长度,如果值为 126127,则使用扩展的负载长度字段。
  • Extended payload length (16/64 bits): 当负载长度大于 125 时使用此字段。
  • Masking-key (32 bits) : 如果 MASK 设置为 1,则此字段用于解码负载数据。
  • Payload Data: 实际传输的数据。

总结

WebSocket 提供了一种在客户端和服务器之间进行实时通信的高效方法。通过一次握手请求,WebSocket 可以建立一个持久的、全双工的通信连接,减少了频繁建立和关闭连接的开销。理解其工作原理和帧格式有助于在应用中更好地使用和调试 WebSocket,从而实现高效的实时通信。

相关推荐
gywl1 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
WTT00112 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
_oP_i2 小时前
HTTP 请求Media typetext/plain application/json text/json区别
网络协议·http·json
杨德杰3 小时前
QT网络(一):主机信息查询
网络·qt
007php0073 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
yang_shengy3 小时前
【JavaEE】网络(6)
服务器·网络·http·https
OkeyProxy4 小时前
HTTP、HTTPS和SOCKS5代理協議
网络协议·https·云计算·代理服务器·海外ip代理
zquwei4 小时前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
Aimin20224 小时前
路由器做WPAD、VPN、透明代理中之间一个
网络
群联云防护小杜5 小时前
如何给负载均衡平台做好安全防御
运维·服务器·网络·网络协议·安全·负载均衡