一 复习和目标
1 复习
- Nodejs实现WebSocket服务器
- Netty实现WebSocket服务器(附带了源码分析)
- Js api实现WebSocket客户端
注:Nodejs使用的Socket.io模块实现,Netty本身对WebSocket有一定的支持,所以这两种实现都相对容易理解,大家自己可以使用自己喜欢的语言实现(参考Nodejs版本,即不需要考虑过多的情况)。
2 目标
- 使用WebSocket协议进行发送Mqtt消息
- 即Mqtt协议作为WebSocket协议的子协议进行通信
注1:WebSocket协议内容不多,但是远远不止这么少。但是学习不要完美主义(即学到一样东西就想着一开始就把这样东西学透),学习要带着目的性。比如:我就是想弄懂为什么前端需要使用WebSocket协议才能发送Mqtt消息?WebSocket为什么需要HTTP协议来进行协议升级协商?HTTP协议为什么基于TCP协议?TCP协议是全双工的为什么HTTP协议不能全双工?等等......
注2:协议目前学习了MQTT、TCP、HTTP和WebSocket,并不是现在学完了,以后就可以不再去学习这些,而是说对于现在的学习目的已经达到了,不需要再花费过多的精力罢了。
二 WireShark抓包
1 WebSocket连接
- 请求升级协议:HTTP -> WebSocket(mqtt)
# 省略无关头部Hypertext Transfer Protocol ???GET /mqtt HTTP/1.1\r\n ???Host: 103.61.37.192:8083\r\n ???Sec-WebSocket-Version: 13\r\n ???Sec-WebSocket-Protocol: mqtt\r\n # 子协议为mqtt ???Sec-WebSocket-Extensions: permessage-deflate\r\n ???Sec-WebSocket-Key: npQCPFw1Pc5G9vqjJyi90w==\r\n ???Connection: keep-alive, Upgrade\r\n ???Upgrade: websocket\r\n ???\r\n
- 响应成功
# 省略无关头部Hypertext Transfer Protocol ???HTTP/1.1 101 Switching Protocols\r\n ???Connection: Upgrade\r\n ???Content-Length: 0\r\n ???Sec-Websocket-Accept: biw/vsujgvKx8B0bfoDnjuxHMgA=\r\n ???Sec-Websocket-Protocol: mqtt\r\n # 确认子协议为mqtt ???Upgrade: websocket\r\n ???\r\n
2 MQTT建立连接
- 客户端 -> 服务器:CONNECT
- 本来MQTT TCP连接可以通过分段或一次传输完成的WebSocket则分成了13次发送
# 发送了13个帧192.168.1.46 ???103.61.37.192 ??WebSocket ??WebSocket Binary [FIN] [MASKED] ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???1... .... = Mask: True ???.000 0001 = Payload length: 1 ???Masking-Key: 0c3cb539 ???Masked payload ???????1C ?????????# 帧序号 ???数据 ??????????????????????????????????????????????????????????# 1 ???????Data: 10 ?-> Header Flags:Connect # 2 ???????Data: 58 ?-> Msg Len:88# 3 ???????Data: 0004 -> Protocol Name Length: 4 # 4 ???????Data: 4d515454 -> Protocol Name: MQTT# 5 ???????Data: 04 -> Version:v3.1.1# 6 ???????Data: c2 # ???????????1... .... = User Name Flag: Set # 用户名# ???????????.1.. .... = Password Flag: Set # 密码# ???????????..0. .... = Will Retain: Not Set # 遗嘱保留# ???????????...0 0... = Qos Level: 0# ???????????.... .0.. = Will Flag: Not Set # 遗嘱# ???????????.... ..1. = Clean Session Flag: Set # 清除会话# ???????????.... ...0 = (Reserverd): Not Set # 固定为0# 7 ???????Data: 003c -> Keep Alive: 60秒# 8 ???????Data: 0011 -> Client ID Length: 17# 9 ???????Data: 6d 71 74 74 6a 73 5f 39 38 33 37 66 65 30 62 61 38 -> ClientId# 10 ??????Data: 000b -> Username Length# 11 ??????Data: 64656c696768742f776562 -> Username# 12 ??????Data: 002c -> Password Length# 13 ??????Data: 45396a4d58416c35523939596b48756350506c3377545468... -> Password
- 服务器 -> 客户端:CONNACK
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???0... .... = Mask: False ???.000 0100 = Payload length: 4 ???Data (4 bytes) ???????Data: 20 02 00 00# 20 -> Header Flags:CONNACK# 02 -> Msg Len:2# 00 -> Acknowledge Flags: 0x00 # 连接确认标志# 00 -> Return Code: Connection Accepted (0) # 连接返回码
3 MQTT的PINGREQ和PINGRESP
- 客户端 -> 服务器:PINGREQ
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???1... .... = Mask: True ???.000 0010 = Payload length: 2 ???Masking-Key: 0657364e ???Data (2 bytes) ???????Data: c000 # C0 -> Header Flags: 0xC0 (Ping Request)# 00 -> Msg Len: 0
- 服务器 -> 客户端 :PINGRESP
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???0... .... = Mask: False ???.000 0010 = Payload length: 2 ???Data (2 bytes) ???????Data: d000# D0 -> Header Flags: 0xD0 (Ping Response) ?# 00 -> Msg Len: 0
4 MQTT的SUBSCRIBE和SUBACK
- 客户端 -> 服务器:SUBSCRIBE
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???1... .... = Mask: True ???.000 0001 = Payload length: 1 ???Masking-Key: d0f56152 ???Data (1 byte) ???????Data: 82 ???????# 帧序号 ???数据 ?????????????????????????????????????????????????????????# 1 ???????Data: 82 ?-> Header Flags: Subscribe Request# 2 ???????Data: 0b ?-> Msg Len:11# 3 ???????Data: a5b2 -> Message Identifier: a5b2# 4 ???????Data: 0006 -> ?Topic Length: 6# 5 ???????Data: 2f 57 6f 72 6c 64 -> Topic:/World# 6 ???????Data: 00 -> Requested QoS:0
- 服务器 -> 客户端 :SUBACK
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???0... .... = Mask: False ???.000 0101 = Payload length: 5 ???Data (5 bytes) ???????Data: 9003a5b200# 90 -> ?Header Flags: Subscribe Ack# 03 -> Msg Len: 3 # a5b2 -> Message Identifier:a5b2# 00 -> 成功
5 MQTT的PUBLISH(Qos0)
# 帧序号 ???数据 ?????????????????????????????????????????????????????????# 1 ???????Data: 30 -> Header Flags: Publish Message# 2 ???????Data: 0d -> ?Msg Len: 13 # 3 ???????Data: 0006 -> Topic Length:6# 4 ???????Data: 2f 57 6f 72 6c 64 -> ?Topic:/World# 5 ???????Data: 68 65 6c 6c 6f -> Message:hello
6 MQTT的DISCONNECT
WebSocket ???1... .... = Fin: True ???.000 .... = Reserved: 0x0 ???.... 0010 = Opcode: Binary (2) ???1... .... = Mask: True ???.000 0010 = Payload length: 2 ???Masking-Key: d70088a5 ???Data (5 bytes) ???????Data: e000# e0 -> Header Flags: Disconnect# 00 -> Msg Len: 0
注1:MQTT报文格式请参考MQTT协议探究(一) MQTT协议探究(二)
注2:MQTT其他报文就不做贴出来了,请自行测试。
注3:协议的学习基本完成,后面结合Netty来加深对协议的复习和补充。
WebSocket协议探究(三):MQTT子协议
原文地址:https://www.cnblogs.com/linzhanfly/p/10108094.html