测试之路--随手记:WebSocket

哈喽大家好,我是小歪~今天在工作中遇到一种协议---WebSocket,之前没怎么接触过,请教了开发大佬,下班回来在网上也查了查相关概念。就准备做个记录。

01 WebSocket协议概念





WebSocket是一种协议。与http类似。都是基于tcp的一种可靠性协议。与http不同的是,http是一种无状态协议。而WebSocket则是一种长链接协议,可以长时间与服务器保持一个连接状态,使客户端与服务端保持持续的数据交流。

如下是网上大佬解释,直接不厚道的粘贴37eaea10c8d43cfff65bd0af25c02241.png

  • 什么是websocket

    • WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的;Websocket是一个持久化的协议

  • websocket的原理

    • websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信在websocket出现之前,web交互一般是基于http协议的短连接或者长连接websocket是一种全新的协议,不属于http无状态协议,协议名为"ws"

  • websocket与http的关系

ead6fdffef50e6efa72118ad3186007b.png

    • 相同点:

      • 都是基于tcp的,都是可靠性传输协议

      • 都是应用层协议

    • 不同点:

      • WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息

      • HTTP是单向的

      • WebSocket是需要浏览器和服务器握手进行建立连接的而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接

    •  联系:

      • WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的

    • 总结(总体过程):

      • 首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;

      • 然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;  

      • 最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。

优快云链接:https://blog.youkuaiyun.com/qq_54773998/article/details/123863493

02 应用场景、总结





请教了开发大佬。就目前很多项目。这种方式比较少见了。常见于消息通信项目,直播间推流项目等,主要还是用于实时通信相关的项目居多。

websocket是一种可以有服务器发起反向发起请求的一种协议,主要数据有更新,就可以推送给客户端使用。与http相比较。http就像是单信道,类似对讲机;websocket就如同是语音电话,双方同时在线,数据交流更直接,更快捷。

最后附上下班路上的随手一拍。北京的今天的傍晚还不错

b25fe8f523a9cfe17b6b9c4d13e1d348.jpeg


                                                                                        随手记-2022年06月14日

<think>我们正在分析一个WebSocket升级请求,该请求用于建立MQTT over WebSocket连接。 请求URL: wss://192.168.2.190:8088/mqtt/ws 请求方法: GET 状态码: 101 Switching Protocols (表示协议切换成功) 请求头(客户端发送): Host: 192.168.2.190:8088 Connection: Upgrade Upgrade: websocket Sec-WebSocket-Key: pBiJ7BsdM1FVUkyWAEkM2A== Sec-WebSocket-Version: 13 Sec-WebSocket-Protocol: mqtt # 表示客户端希望使用MQTT子协议 Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits # 压缩扩展 ... 以及其他常规头 响应头(服务器返回): Connection: upgrade Upgrade: websocket sec-websocket-accept: 0jEh9vXCDZfV6bcABum9tbRAy9I= # 服务器对Sec-WebSocket-Key的响应 sec-websocket-extensions: permessage-deflate; client_max_window_bits=15 # 服务器确认的压缩参数 sec-websocket-protocol: mqtt # 服务器同意使用MQTT子协议 Server: nginx/1.21.4 解读: 这是一个WebSocket握手请求,用于将HTTP连接升级为WebSocket连接,并且指定使用MQTT协议(即MQTT over WebSocket)。 服务器返回101状态码,表示已经成功升级到WebSocket协议。之后,通信将使用WebSocket帧,并在WebSocket连接上传输MQTT协议包。 代码实现:下面是一个简单的Node.js服务器,使用ws库来处理WebSocket连接,并支持MQTT协议。 注意:实际生产环境可能需要使用专门的MQTT代理(如Mosquitto, EMQ X等),这里仅演示WebSocket握手部分。 由于我们无法直接实现完整的MQTT代理,这里只展示如何升级到WebSocket并处理连接。</think># WebSocket 升级请求详解:MQTT over WebSocket 实现 ## 完整请求分析 ```mermaid sequenceDiagram participant Client as 浏览器客户端 participant Server as Nginx服务器 participant MQTT as MQTT代理 Client->>Server: GET wss://192.168.2.190:8088/mqtt/ws Note right of Client: Sec-WebSocket-Key: pBiJ7BsdM1FVUkyWAEkM2A==<br/>Sec-WebSocket-Protocol: mqtt Server->>MQTT: 转发WebSocket请求 MQTT-->>Server: 确认协议升级 Server->>Client: HTTP 101 Switching Protocols Note left of Server: sec-websocket-accept: 0jEh9vXCDZfV6bcABum9tbRAy9I=<br/>sec-websocket-protocol: mqtt Client->>Server: WebSocket帧(MQTT协议数据) Server->>MQTT: 转换并转发MQTT消息 MQTT-->>Server: MQTT响应 Server->>Client: WebSocket帧(MQTT响应数据) ``` ## 核心组件解析 ### 1. WebSocket 握手过程 ```python # WebSocket 握手验证算法 import base64 import hashlib def generate_accept(key): """生成Sec-WebSocket-Accept响应头""" magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" combined = key + magic_string sha1 = hashlib.sha1(combined.encode()).digest() return base64.b64encode(sha1).decode() # 客户端提供的密钥 client_key = "pBiJ7BsdM1FVUkyWAEkM2A==" # 计算服务端响应密钥 accept_key = generate_accept(client_key) print(f"计算出的Accept Key: {accept_key}") # 输出: 0jEh9vXCDZfV6bcABum9tbRAy9I= ``` ### 2. MQTT over WebSocket 实现 ```javascript // 浏览器端实现 - 使用MQTT.js库 const mqtt = require('mqtt'); // 创建MQTT客户端 const client = mqtt.connect('wss://192.168.2.190:8088/mqtt/ws', { protocolVersion: 4, // MQTT v3.1.1 rejectUnauthorized: false, // 允许自签名证书 clientId: 'web-client-' + Math.random().toString(16).substr(2, 8), protocol: 'wss', headers: { 'Sec-WebSocket-Protocol': 'mqtt' } }); // 连接事件处理 client.on('connect', () => { console.log('成功连接到MQTT代理'); // 订阅主题 client.subscribe('sensors/#', (err) => { if (!err) { console.log('成功订阅传感器主题'); // 发布消息 client.publish('sensors/temperature', '25.6°C'); } }); }); // 接收消息 client.on('message', (topic, message) => { console.log(`收到消息 [${topic}]: ${message.toString()}`); }); // 错误处理 client.on('error', (err) => { console.error('MQTT连接错误:', err); }); ``` ## Nginx 配置解析 ```nginx # /etc/nginx/nginx.conf http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 8088 ssl; server_name 192.168.2.190; # SSL配置 ssl_certificate /etc/ssl/certs/server.crt; ssl_certificate_key /etc/ssl/private/server.key; ssl_protocols TLSv1.2 TLSv1.3; # WebSocket代理配置 location /mqtt/ws { proxy_pass http://mqtt_broker:1883; # 代理到MQTT服务 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # WebSocket协议头处理 proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key; proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version; proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol; # 超时设置 proxy_read_timeout 86400s; # 24小时 } } } ``` ## 协议升级流程详解 ### 1. 握手阶段 ```mermaid graph LR A[客户端] -->|1. GET /mqtt/ws| B[Nginx] B -->|2. 转发请求| C[MQTT代理] C -->|3. 接受协议升级| B B -->|4. HTTP 101| A ``` ### 2. 数据传输阶段 ```mermaid graph LR A[浏览器] -->|WebSocket帧| B[Nginx] B -->|解码WebSocket| C[原始数据] C -->|MQTT协议| D[MQTT代理] D -->|处理消息| E[存储/转发] E -->|响应| D D -->|MQTT响应| B B -->|编码为WebSocket帧| A ``` ## 安全机制分析 ### 1. WebSocket安全 (wss) ```mermaid pie title 安全机制组成 “TLS加密” : 45 “认证机制” : 25 “协议验证” : 20 “数据完整性” : 10 ``` ### 2. 认证实现代码 ```javascript // MQTT代理端认证处理 const mosca = require('mosca'); const settings = { port: 1883, http: { port: 8088, bundle: true, static: './' } }; const server = new mosca.Server(settings); // 客户端认证 server.authenticate = function(client, username, password, callback) { // 数据库验证用户凭证 db.verifyUser(username, password.toString(), (valid) => { if (valid) { console.log(`用户 ${username} 认证成功`); callback(null, true); } else { console.warn(`认证失败: ${username}`); callback(null, false); } }); }; // 主题授权 server.authorizePublish = function(client, topic, payload, callback) { // 检查客户端是否有发布权限 if (client.user === 'admin' || topic.startsWith(`clients/${client.id}`)) { callback(null, true); } else { callback(null, false); } }; server.on('ready', () => { console.log('MQTT代理运行在端口 1883'); }); ``` ## 性能优化策略 ### 1. WebSocket压缩 ```nginx # Nginx配置启用压缩 http { gzip on; gzip_types text/plain application/json; # WebSocket压缩 map $http_accept_encoding $ws_encoding { default ""; "~*deflate" "permessage-deflate; client_max_window_bits=15"; } server { location /mqtt/ws { # 添加压缩响应头 add_header Sec-WebSocket-Extensions $ws_encoding; } } } ``` ### 2. 负载均衡配置 ```nginx upstream mqtt_cluster { zone backend 64k; server mqtt1:1883; server mqtt2:1883; server mqtt3:1883; keepalive 32; } server { location /mqtt/ws { proxy_pass http://mqtt_cluster; # 启用会话保持 proxy_set_header MQTT-Client-ID $http_sec_websocket_key; } } ``` ## 常见问题排查 ### 1. 连接失败诊断表 | 问题现象 | 可能原因 | 解决方案 | |---------|---------|---------| | 无法建立连接 | 证书问题 | 检查证书链是否完整 | | 101响应但无数据 | 代理配置错误 | 验证Nginx到MQTT的连通性 | | 间歇性断开 | 超时设置不当 | 增加`proxy_read_timeout`值 | | 协议不被支持 | 客户端/服务端版本不匹配 | 检查MQTT协议版本 | ### 2. 调试工具推荐 ```bash # 使用websocat测试连接 websocat -v wss://192.168.2.190:8088/mqtt/ws # 使用tcpdump抓包分析 tcpdump -i any -s 0 -w mqtt.pcap 'port 8088' ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值