WebSocket協議探究(三):MQTT子協議


一 復習和目標

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來加深對協議的復習和補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM