WebSocket over TCP连接异常:握手成功后CONNECT请求无响应
问题分析:WebSocket握手后发送MQTT请求返回空响应的原因
兄弟,你在WebSocket握手成功后发送的MQTT连接请求完全走错路了,这就是服务器返回空响应的核心原因,具体问题有两个:
1. 混淆了HTTP CONNECT和MQTT CONNECT的用法
WebSocket握手完成后,你和服务器之间已经建立了基于WebSocket的双向二进制通道,此时不需要再发送任何HTTP格式的请求了。你写的这段请求:
"CONNECT clientId-nVqGddbrRK@broker.mqttdashboard.com:8000 HTTP/1.1 " + "host: broker.mqttdashboard.com " + " "
这是HTTP代理的CONNECT请求格式,和MQTT over WebSocket半毛钱关系都没有,服务器根本识别不了这种不伦不类的请求,自然不会给你有效响应。
2. MQTT over WebSocket的正确发送方式
MQTT over WebSocket要求你把标准的MQTT二进制报文封装在WebSocket的二进制帧中发送,而不是文本格式的内容。以MQTT 3.1.1为例,正确的CONNECT报文是有固定二进制结构的:
- 第一个字节:
0x10(MQTT CONNECT报文类型,固定值) - 第二个字节:剩余长度(根据后续内容计算)
- 后续依次是:协议名("MQTT")、协议级别(
0x04)、连接标志、保持时间、客户端ID等字段。
给你一个简单的C#示例,用来构建基础的MQTT CONNECT二进制报文并封装成WebSocket帧发送:
// 构建MQTT CONNECT核心报文 List<byte> connectPacket = new List<byte>(); // 报文类型标识(CONNECT) connectPacket.Add(0x10); // 先占位剩余长度,后面再计算替换 connectPacket.Add(0); // 协议名:"MQTT",先写长度再写内容 connectPacket.AddRange(BitConverter.GetBytes((ushort)4).Reverse()); connectPacket.AddRange(Encoding.ASCII.GetBytes("MQTT")); // 协议级别(MQTT 3.1.1对应0x04) connectPacket.Add(0x04); // 连接标志(开启clean session) connectPacket.Add(0x02); // 保持连接时间(60秒) connectPacket.AddRange(BitConverter.GetBytes((ushort)60).Reverse()); // 客户端ID string clientId = "clientId-nVqGddbrRK"; connectPacket.AddRange(BitConverter.GetBytes((ushort)clientId.Length).Reverse()); connectPacket.AddRange(Encoding.ASCII.GetBytes(clientId)); // 计算剩余长度并替换占位 byte remainingLength = (byte)(connectPacket.Count - 2); connectPacket[1] = remainingLength; // 封装成WebSocket二进制帧发送 List<byte> webSocketFrame = new List<byte>(); webSocketFrame.Add(0x82); // FIN标记 + 二进制帧类型 webSocketFrame.Add((byte)connectPacket.Count); // 载荷长度 webSocketFrame.AddRange(connectPacket); // 发送最终的WebSocket帧 sock.Send(webSocketFrame.ToArray());
另外提个小建议:直接用Socket处理WebSocket帧其实挺繁琐的,C#里有现成的ClientWebSocket类,它会自动帮你处理WebSocket的帧封装和解封,你只需要专注于发送MQTT二进制报文就行,能省不少事。
内容的提问来源于stack exchange,提问作者Mrg Gek
相关产品推荐
相关产品推荐

