MQTT协议分析

Publish: November 3, 2016 Category: 小玩具,编程 2 Comments

<div class=WordSection1 style='layout-grid:15.6pt'>

<p class=MsoNormal>比较全面的<span
lang=EN-US>MQTT</span>协议分析文档</p>

<p class=MsoNormal>目录</p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>使用研究</span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>协议分析</span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>连接和心跳</span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>发布流程</span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>消息流</span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>订阅流程</span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span style='font-size:14.0pt;
font-family:宋体;color:red'>使用研究</span>:</p>

<p class=MsoNormal>服务端:<span lang=EN-US><a
href="http://mosquitto.org/download/"><span style='color:blue'>http://mosquitto.org/download/<;/span></span></p>

<p class=MsoNormal>编译安装:<span lang=EN-US><a
href="http://blog.csdn.net/xukai871105/article/details/39252653"><span
style='color:blue'>http://blog.csdn.net/xukai871105/article/details/39252653<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal>配置说明</p>

<p class=MsoNormal><span lang=EN-US><a
href="http://cswei.blog.51cto.com/3443978/1225617"><span style='color:blue'>http://cswei.blog.51cto.com/3443978/1225617<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US>PHP</span>实现</p>

<p class=MsoNormal><span lang=EN-US><a
href="https://github.com/mgdm/Mosquitto-PHP"><span style='color:blue'>https://github.com/mgdm/Mosquitto-PHP<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US>LUA</span>实现</p>

<p class=MsoNormal><span lang=EN-US><a
href="https://github.com/flukso/lua-mosquitto"><span style='color:blue'>https://github.com/flukso/lua-mosquitto<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal>译文 </p>

<p class=MsoNormal><span lang=EN-US><a
href="http://my.oschina.net/scholer/blog/296402"><span style='color:blue'>http://my.oschina.net/scholer/blog/296402<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US>PHP</span>环境相关</p>

<p class=MsoNormal><span lang=EN-US><a
href="http://www.hivemq.com/blog/mqtt-client-library-encyclopedia-mosquitto-php"><span
style='color:blue'>http://www.hivemq.com/blog/mqtt-client-library-encyclopedia-mosquitto-php<;/span></span></p>

<p class=MsoNormal><span lang=EN-US><a
href="http://wingsquare.com/blog/developing-php-client-for-mqtt-using-mosquitto-php-library/"><span
style='color:blue'>http://wingsquare.com/blog/developing-php-client-for-mqtt-using-mosquitto-php-library/<;/span></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US>mqtt </span>遇到的错误收集:</p>

<p class=MsoNormal><span lang=EN-US>Error:
Invalid user 'mosquitto'  </span>没有<span lang=EN-US>mosquitto</span>的用户</p>

<p class=MsoNormal><span style='font-size:12.0pt;
font-family:"Hiragino Sans GB W3","serif";color:#4C402B;background:white'>两种解决办法:</span></p>

<p class=MsoNormal><span style='font-size:9.0pt;
font-family:"Arial","sans-serif";color:#4C402B;background:white'>(<span
lang=EN-US>1</span>)修改配置文件<span lang=EN-US>:mosquitto.conf </span>,增加登录的用户,例如当前登录用户为<span
lang=EN-US>root</span></span></p>

<p class=MsoNormal align=center style='text-align:center'><a
name=18wfuo1478263973355><span lang=EN-US><img border=0 width=205
height=186 id="Drawing 0" src="http://img.evenvi.com//image001.jpg"
alt=60444674196.jpeg></span></p>

<p class=MsoNormal align=center style='text-align:center'><a
name=15eyde1478263973355><span lang=EN-US style='font-size:9.0pt;
font-family:"Arial","sans-serif";color:#4C402B;background:white'> </span></p>

<p class=MsoNormal><span style='font-size:9.0pt;
font-family:"Arial","sans-serif";color:#4C402B;background:white'>(<span
lang=EN-US>1</span>)执行命令增加当前用户:</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-size:9.0pt;font-family:"Arial","sans-serif";color:#4C402B;
background:white'> adduser mosquitto</span></p>

<p class=MsoNormal><span style='font-size:9.0pt;
font-family:"Arial","sans-serif";color:#4C402B;background:white'>如下图:</span></p>

<p class=MsoNormal align=center style='text-align:center'><a
name=53oxbb1478263973355><span lang=EN-US><img border=0 width=553
height=172 id="Drawing 1" src="http://img.evenvi.com//image002.jpg"
alt=75166231759.jpeg></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US>•</span><span
lang=EN-US style='font-family:"Calibri","sans-serif";color:#4C4C4C'>PINGREQ/PINGRESP 
</span><span style='font-family:"Calibri","sans-serif";color:#4C4C4C'>心跳</span></p>

<p class=MsoNormal><span style='font-family:
宋体;color:#4C4C4C'>功能测试:</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>1) Connect</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>2) Disconnect</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>3) Subscribe</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>4) UnSubscribe</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>5) Publish QOS0,QOS1,
QOS2</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>6) Retain </span><span
style='font-family:"Arial","sans-serif";color:#4C4C4C'>【</span><span
style='font-family:宋体;color:#4C4C4C'>为新来的订阅者推送那些已经存在的持久化消息】</span></p>

<p class=MsoNormal><span lang=EN-US
style='font-family:"Arial","sans-serif";color:#4C4C4C'>7) Will </span><span
style='font-family:宋体;color:#4C4C4C'>特性【发布遗愿】</span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal align=center style='text-align:center'><a
name=63wohh1478263973355><span style='font-size:14.0pt;font-family:宋体;
color:red'>协议分析:</span></p>

<p class=MsoNormal><span style='font-size:11.0pt;
color:#666666'>先说一下整个协议的构造,整体上协议可拆分为:</span></p>

<p class=MsoNormal style='line-height:115%'><span
lang=EN-US style='font-size:11.0pt;line-height:115%;color:#666666'> 
          </span><span lang=EN-US
style='font-size:12.0pt;line-height:115%;color:#666666'>      </span>
<span
lang=EN-US style='font-size:12.0pt;line-height:115%;color:red'>  </span>
<span
style='font-size:12.0pt;line-height:115%;color:red'>固定头部<span lang=EN-US>+</span>可变头部<span
lang=EN-US>+</span>消息体</span>
</p>

<p class=MsoNormal><span style='font-size:
12.0pt;color:red'>固定头部</span>
</p>

<p class=MsoNormal><span lang=EN-US><img
border=0 width=553 height=57 id="Drawing 2" src="http://img.evenvi.com//image003.gif"
alt=002110437924.png></span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal>协议头占两个字节</p>

<p class=MsoNormal><span lang=EN-US
style='background:yellow'>BYTE1</span></p>

<p class=MsoNormal>【<span lang=EN-US>RETAIN</span>】<span
lang=EN-US>0 : </span>保持;针对<span lang=EN-US>PUBLISH</span>消息。</p>

<p class=MsoNormal style='text-indent:21.0pt'><span
lang=EN-US>1 </span>表示发送的消息一直持久保存,不受服务端重启影响,不但要发送给当前订阅者,并且以后新来的订阅者订阅了此<span
lang=EN-US>topic name</span>的订阅者会马上得到推送,新订阅者只会接受一次<span lang=EN-US>flag</span>为<span
lang=EN-US>1</span>的消息。</p>

<p class=MsoNormal style='text-indent:21.0pt'><span
lang=EN-US>0 </span>仅为当前订阅者推送此消息,假如收到一个空消息体(<span lang=EN-US>zero_length_payload</span>)<span
lang=EN-US>RETAIN=1</span>,已存在<span lang=EN-US>topic name</span>的<span
lang=EN-US>publish</span>消息,服务器可以删除对应已被持久化的<span lang=EN-US>PUBLISH</span>消息。</p>

<p class=MsoNormal>【<span lang=EN-US>Qos level</span>】<span
lang=EN-US>1</span>、<span lang=EN-US>2 : Quality of Service</span>服务质量,使用两个二进制表示的<span
lang=EN-US>publish</span>类型消息</p>

<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:11.0pt;font-family:
"Verdana","sans-serif"'>QoS value</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:11.0pt;font-family:
"Verdana","sans-serif"'>bit 2</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:11.0pt;font-family:
"Verdana","sans-serif"'>bit 1</span>
</p>
</td>
<td colspan=3 style='border:solid windowtext 1.0pt;border-left:none;
padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:11.0pt;font-family:
"Verdana","sans-serif"'>Description</span>
</p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>至多一次</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>发完即丢弃</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'><=1</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>至少一次</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>需要确认回复</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>>=1</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>2</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>只有一次</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>需要确认回复</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>=1</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>3</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td colspan=3 style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>待用,保留位置</span></p>
</td>
</tr>
</table>

<p class=MsoNormal>【<span lang=EN-US>DUP flag</span>】<span
lang=EN-US>3 </span>打开标志</p>

<p class=MsoNormal style='text-indent:21.0pt'>保证消息可靠传输,默认为<span
lang=EN-US>0</span>,只占用一个字节,表示第一次发送。不能用于检测消息重发送等。只适用于客户端或者服务端尝试重发<span
lang=EN-US>PUBLISH</span>、<span lang=EN-US>PUBREL</span>、<span lang=EN-US>SUBCRIBE</span>或<span
lang=EN-US>UNSUBSCRIBE</span>消息注意需要满足以下条件:当<span lang=EN-US>QOS>0 </span>消息需要回复确认
<span style='font-size:10.0pt;font-family:"Verdana","sans-serif";background:
white'>此时,在可变头部需要包含消息<span lang=EN-US>ID</span>。当值为<span lang=EN-US>1</span>时,表示当前消息先前已经被传送过。</span></p>

<p class=MsoNormal><span style='font-size:10.0pt;
font-family:"Verdana","sans-serif";background:white'>【<span lang=EN-US>Message
Type</span>】<span lang=EN-US>4</span>、<span lang=EN-US>5</span>、<span
lang=EN-US>6</span>、<span lang=EN-US>7 </span>消息类型<span lang=EN-US>x</span></span></p>

<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>Mnemonic</span></p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>Enumeration</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>Description</span></p>
</td>
</tr>
<tr style='height:23.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:23.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Reserved</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:23.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:23.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Reserved
 //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>保留待用</span></p>
</td>
</tr>
<tr style='height:16.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:16.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>CONNECT</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:16.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:16.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Client
request to connect to Server  //</span><span style='font-size:9.0pt;
font-family:"Verdana","sans-serif"'>客户端请求连接到服务端</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>CONNACK</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>2</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Connect
Acknowledgment //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>请求应答,请求连接确认</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PUBLISH</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>3</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Publish
message  //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>发布消息</span></p>
</td>
</tr>
<tr style='height:19.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PUBACK</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>4</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Publish
Acknowledgment  //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>发布应答,发布确认</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PUBREC</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>5</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Publish
Received (assured delivery part 1) //</span><span style='font-size:9.0pt;
font-family:"Verdana","sans-serif"'>发布已接收,保证传递<span lang=EN-US>1</span></span></p>
</td>
</tr>
<tr style='height:18.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:18.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PUBREL</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>6</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:18.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Publish
Release (assured delivery part 2)   //</span><span style='font-size:
9.0pt;font-family:"Verdana","sans-serif"'>发布释放,保证传递<span lang=EN-US>2</span></span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PUBCOMP</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>7</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Publish
Complete (assured delivery part 3)  //</span><span style='font-size:
9.0pt;font-family:"Verdana","sans-serif"'>发布完成,保证传递<span lang=EN-US>3</span></span></p>
</td>
</tr>
<tr style='height:16.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:16.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>SUBSCRIBE</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:16.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>8</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:16.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Client
Subscribe request  //</span><span style='font-size:9.0pt;font-family:
"Verdana","sans-serif"'>客户端订阅请求</span></p>
</td>
</tr>
<tr style='height:19.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>SUBACK</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>9</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Subscribe
Acknowledgment  //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>订阅应答,订阅请求</span></p>
</td>
</tr>
<tr style='height:20.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:20.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>UNSUBSCRIBE</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:20.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>10</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:20.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Client
Unsubscribe request  //</span><span style='font-size:9.0pt;font-family:
"Verdana","sans-serif"'>客户端取消订阅请求</span></p>
</td>
</tr>
<tr style='height:21.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:21.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>UNSUBACK</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:21.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>11</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:21.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Unsubscribe
Acknowledgment  //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>取消订阅应答,取消订阅确认</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PINGREQ</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>12</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PING
Request  //ping</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>请求</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PINGRESP</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>13</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>PING
Response  //ping</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>响应</span></p>
</td>
</tr>
<tr style='height:19.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>DISCONNECT</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>14</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:19.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Client
is Disconnecting  //</span><span style='font-size:9.0pt;font-family:
"Verdana","sans-serif"'>客户端断开连接</span></p>
</td>
</tr>
<tr style='height:17.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Reserved</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>15</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:17.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Reserved
  //</span><span style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>保留待用</span></p>
</td>
</tr>
</table>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US
style='background:yellow'>BYTE2</span></p>

<p class=MsoNormal style='text-indent:21.0pt'>是用来保存接下去的变长头部<span
lang=EN-US>+</span>消息体的总大小的。</p>

<p class=MsoNormal style='text-indent:21.0pt'>但是不是并不是直接保存的,同样也是可以扩展的,其机制是,前<span
lang=EN-US>7</span>位用于保存长度,后一部用做标识。举个例了,即如果计算出后面的大小为<span lang=EN-US>0<length<=127</span>的,正常保存,如果是<span
lang=EN-US>127<length<16383</span>的,则需要二个字节保存了,将第一个字节的最大的一位置<span
lang=EN-US>1,</span>表示未完。然后第二个字节继续存。拿<span lang=EN-US>130</span>来说,第一个字节存<span
lang=EN-US>10000011,</span>第二个字节存<span lang=EN-US>000000001</span>,也就是<span
lang=EN-US>0x83,0x01,</span>把两个字节连起来看,第二个字节权重从<span lang=EN-US>2</span>的<span
lang=EN-US>8</span>次开始。同起可以加第<span lang=EN-US>3</span>个字节,最多可以加至第<span
lang=EN-US>4</span>个字节。故<span lang=EN-US>MQTT</span>协议最多可以实现<span lang=EN-US>268 435 455
(0xFF, 0xFF, 0xFF, 0x7F)</span>将近<span lang=EN-US>256M</span>的数据。可谓能伸能缩。</p>

<p class=MsoNormal style='text-indent:21.0pt'><span
lang=EN-US> </span></p>

<p class=MsoNormal style='text-indent:21.0pt'>单个字节最大值,<span
lang=EN-US>01111111=>0x7f=>127 </span></p>

<p class=MsoNormal style='text-indent:21.0pt'><span
style='font-size:10.0pt;font-family:"Verdana","sans-serif";background:white'>时<span
lang=EN-US>MQTT</span>协议最多允许<span lang=EN-US>4</span>个字节表示剩余长度。那么最大长度为:<span
lang=EN-US>0xFF,0xFF,0xFF,0x7F</span>,二进制表示为<span lang=EN-US>:11111111,11111111,11111111,01111111</span>,十进制:<span
lang=EN-US>268435455 byte=261120KB=256MB=0.25GB </span>四个字节之间值的范围:</span></p>

<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>Digits</span></p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>From</span></p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>To</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>1</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>0
(0x00)</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>127
(0x7F)</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>2</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>128
(0x80, 0x01)</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>16
383 (0xFF, 0x7F)</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>3</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>16
384 (0x80, 0x80, 0x01)</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>2
097 151 (0xFF, 0xFF, 0x7F)</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>4</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>2
097 152 (0x80, 0x80, 0x80, 0x01)</span></p>
</td>
<td style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>268
435 455 (0xFF, 0xFF, 0xFF, 0x7F)</span></p>
</td>
</tr>
</table>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span style='font-size:
12.0pt;color:red'>可变头部</span>
</p>

<p class=MsoNormal><span style='font-size:10.0pt;
font-family:"Verdana","sans-serif";background:white'>固定头部仅定义了消息类型和一些标志位,一些消息的元数据,需要放入可变头部中。<span
style='color:red'>可变头部内容字节长度<span lang=EN-US> + Playload/</span>负荷字节长度<span
lang=EN-US> = </span>剩余长度</span>,这个是需要牢记的。可变头部,包含了协议名称,版本号,连接标志,用户授权,心跳时间等内容,这部分和后面要讲到的<span
lang=EN-US>CONNECT</span>消息类型,有重复,暂时略过。</span></p>

<p class=MsoNormal><span lang=EN-US><img
border=0 width=553 height=404 id="Drawing 3"
src="http://img.evenvi.com//image004.jpg" alt=218212825500.png></span></p>

<p class=MsoNormal><span style='font-family:
"Helvetica Neue","serif";color:#333333;background:white'>这个是可变头部的全貌。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>1</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、首先最上面的<span lang=EN-US>8</span>个字节是<span
lang=EN-US>Protocol Name(</span>编码名<span lang=EN-US>)</span>,<span lang=EN-US>UTF</span>编码的字符<span
lang=EN-US>“MQIsdp”</span>,头两个是编码名提长为<span lang=EN-US>6</span>。</span></p>

<p class=MsoNormal style='line-height:106%'><span
style='font-family:"Helvetica Neue","serif";color:#333333;background:white'>这里多说一些,接下去的协议多采用这种方式组合,即头两个字节表示下一部分的长,然后后面跟上内容。这里头两个字节长为<span
lang=EN-US>6</span>,下面跟<span lang=EN-US>6</span>个字符<span lang=EN-US>“MQIsdp”</span>。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>2</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、<span lang=EN-US>Protocol Version</span>,协议版本号,<span
lang=EN-US>v3 </span>也是固定的。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>3</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、<span lang=EN-US>Connect Flag</span>,连接标识,有点像固定头部的。<span
lang=EN-US>8</span>位分别代表不同的标志。第<span lang=EN-US>1</span>个字节保留。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>Clean Session,Will flag</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>,<span lang=EN-US>Will Qos, Will Retain</span>都是相对于<span
lang=EN-US>CONNECT</span>消息来说的。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>Clean Session:0</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>表示如果订阅的客户机断线了,那么要保存其要推送的消息,如果其重新连接时,则将这些消息推送。</span></p>

<p class=MsoNormal style='line-height:86%'><span
lang=EN-US style='font-size:10.0pt;line-height:86%;font-family:"Source Code Pro","serif";
color:#657B83'>                       
1</span><span style='font-size:10.0pt;line-height:86%;font-family:"Source Code Pro","serif";
color:#657B83'>表示消除,表示客户机是第一次连接,消息所以以前的连接信息。 </span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>Will Flag</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>,表示如果客户机在不是在发送<span lang=EN-US>DISCONNECT</span>消息中断,比如<span
lang=EN-US>IO</span>错误等,将些置为<span lang=EN-US>1,</span>要求重传。并且下且的<span
lang=EN-US>WillQos</span>和<span lang=EN-US>WillRetain</span>也要设置,消息体中的<span
lang=EN-US>Topic</span>和<span lang=EN-US>MessageID</span>也要设置,就是表示发生了错误,要重传。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>Will Qos</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>,在<span lang=EN-US>CONNECT</span>非正常情况下设置,一般如果标识了<span
lang=EN-US>WillFlag</span>,那么这个位置也要标识。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>Will RETAIN</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>:同样在<span lang=EN-US>CONNECT</span>中,如果标识了<span
lang=EN-US>WillFlag,</span>那么些位也一定要标识</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>usename flag</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>和<span lang=EN-US>passwordflag</span>,用来标识是否在消息体中传递用户和密码,只有标识了,消息体中的用户名和密码才用效,只标记密码而不标记用户名是不合法的。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>4</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、<span lang=EN-US>Keep Alive</span>,表示响应时间,如果这个时间内,连接或发送操作未完成,则断开<span
lang=EN-US>tcp</span>连接,表示离线。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>5</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、<span lang=EN-US>Connect Return Code</span>即通常于<span
lang=EN-US>CONNACK</span>消息中,表示返回的连接情况,我可以通过此检验连接情况。</span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US><img
border=0 width=553 height=221 id="Drawing 4"
src="http://img.evenvi.com//image005.gif" alt=bVyoew.png></span></p>

<p class=MsoNormal style='line-height:106%'><span
lang=EN-US style='font-family:"Helvetica Neue","serif";color:#333333;
background:white'>6</span><span style='font-family:"Helvetica Neue","serif";
color:#333333;background:white'>、<span lang=EN-US>Topic Name</span>,订阅消息标识,<span
lang=EN-US>MQTT</span>是基于订阅<span lang=EN-US>/</span>发布的消息,那么这个就是消息订阅的标识,像新闻客户端里的订阅不同的栏目一样。用于区别消息的推送类别。</span></p>

<p class=MsoNormal style='line-height:106%'><span
style='font-family:"Helvetica Neue","serif";color:#333333;background:white'>主要用于<span
lang=EN-US>PUBLISH</span>和<span lang=EN-US>SUBSCRIBE</span>中。最大可支持<span
lang=EN-US>32767</span>个字符,即<span lang=EN-US>4</span>个字节。</span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span style='font-size:
12.0pt;color:red'>消息体</span>
<span lang=EN-US style='font-size:10.0pt;
font-family:"Verdana","sans-serif";background:white'>(Playload/</span>
<span
style='font-size:10.0pt;font-family:"Verdana","sans-serif";background:white'>消息体<span
lang=EN-US>/</span>负荷<span lang=EN-US>)</span></span>
</p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>消息体主要是为配合固定<span lang=EN-US>/</span>可变头部命令(比如<span
lang=EN-US>CONNECT</span>可变头部<span lang=EN-US>User name</span>标记若为<span
lang=EN-US>1</span>则需要在消息体中附加用户名称字符串)而存在。</span></p>

<p class=MsoNormal style='line-height:102%'><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>CONNECT/SUBSCRIBE/SUBACK/PUBLISH</span><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>等消息有消息体。<span lang=EN-US>PUBLISH</span>的消息体以二进制形式对待。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>请记住,<span lang=EN-US>MQTT</span>协议只允许在<span lang=EN-US>PUBLISH</span>类型消息体中使用自定义特性,在固定<span
lang=EN-US>/</span>可变头部想加入自定义私有特性,就免了吧。这也是为了协议免于流于形式,变得很分裂也为了兼顾现有客户端等。比如支持压缩等,那就可以在<span
lang=EN-US>Playload</span>中定义数据支持,在应用中进行读取处理。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>这部分会在后面详细论述。</span></p>

<p class=MsoNormal><span style='font-size:
10.0pt;font-family:"Verdana","sans-serif";background:white'>消息标识符<span
lang=EN-US>/</span>消息<span lang=EN-US>ID</span></span>
</p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>固定头中的<span lang=EN-US>QoS level</span>标志值为<span lang=EN-US>1</span>或<span
lang=EN-US>2</span>时才会在:<span lang=EN-US>PUBLISH</span>,<span lang=EN-US>PUBACK</span>,<span
lang=EN-US>PUBREC</span>,<span lang=EN-US>PUBREL</span>,<span lang=EN-US>PUBCOMP</span>,<span
lang=EN-US>SUBSCRIBE</span>,<span lang=EN-US>SUBACK</span>,<span lang=EN-US>UNSUBSCRIBE</span>,<span
lang=EN-US>UNSUBACK</span>等消息的可变头中出现。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>一个<span lang=EN-US>16</span>位无符号位的<span lang=EN-US>short</span>类型值(值不能为<span
lang=EN-US> 0</span>,<span lang=EN-US>0</span>做保留作为无效的消息<span lang=EN-US>ID</span>),仅仅要求在一个特定方向(服务器发往客户端为一个方向,客户端发送到服务器端为另一个方向)的通信消息中必须唯一。比如客户端发往服务器,有可能存在服务器发往客户端会同时存在重复,但不碍事。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>可变头部中,需要两个字节的顺序是<span lang=EN-US>MSB(Most Significant Bit)
LSB(Last/Least Significant Bit)</span>,翻译成中文就是,最高有效位,最低有效位。最高有效位在最低有效位左边<span
lang=EN-US>/</span>上面,表示这是一个大端字节<span lang=EN-US>/</span>网络字节序,符合人的阅读习惯,高位在最左边。</span></p>

<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
style='border-collapse:collapse;border:none'>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US style='font-family:"Verdana","sans-serif"'>bit</span></p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>7</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>6</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>5</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>4</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>3</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>2</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>1</span>
</p>
</td>
<td style='border:solid windowtext 1.0pt;border-left:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span
lang=EN-US style='font-family:"Verdana","sans-serif"'>0</span>
</p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US> </span></p>
</td>
<td colspan=8 style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Message Identifier
MSB</span></p>
</td>
</tr>
<tr style='height:24.0pt'>
<td style='border:solid windowtext 1.0pt;border-top:none;padding:0cm 5.4pt 0cm 5.4pt;
height:24.0pt'>
<p class=MsoNormal><span lang=EN-US> </span></p>
</td>
<td colspan=8 style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;
border-right:solid windowtext 1.0pt;padding:0cm 5.4pt 0cm 5.4pt;height:24.0pt'>
<p class=MsoNormal align=center style='text-align:center'><span lang=EN-US
style='font-size:9.0pt;font-family:"Verdana","sans-serif"'>Message Identifier
LSB</span></p>
</td>
</tr>
</table>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>但凡如此表示的,都可以视为一个<span lang=EN-US>16</span>位无符号<span
lang=EN-US>short</span>类型整数,两个字节表示。在<span lang=EN-US>JAVA</span>中处理比较简单:</span></p>

<p class=MsoNormal style='line-height:102%'><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"monospace","serif";
color:#444444;background:white'>DataInputStream</span>
<span lang=EN-US
style='font-size:10.0pt;line-height:102%;font-family:"monospace","serif";
color:#880000;background:white'>.readUnsignedShort</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>或者</span></p>

<p class=MsoNormal style='line-height:102%'><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"monospace","serif";
color:#444444;background:white'>in</span>
<span lang=EN-US style='font-size:
10.0pt;line-height:102%;font-family:"monospace","serif";color:#444444;
background:white'>.read() * </span><span lang=EN-US style='font-size:10.0pt;
line-height:102%;font-family:"monospace","serif";color:#880000;background:white'>0xFF</span><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"monospace","serif";
color:#444444;background:white'> + in.read();</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>最大长度可为:<span lang=EN-US> 65535</span></span></p>

<p class=MsoNormal><span style='font-family:
宋体;color:#4C4C4C'>基于<span lang=EN-US>workmen</span>的客户端实现:</span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US
style='font-size:14.0pt;font-family:宋体;color:red'>MQTT</span><span
style='font-size:14.0pt;font-family:宋体;color:red'>协议<span lang=EN-US>--</span>连接和心跳</span></p>

<p class=MsoNormal><span lang=EN-US> </span></p>

<p class=MsoNormal><span lang=EN-US><img
border=0 width=553 height=517 id="Drawing 5"
src="http://img.evenvi.com//image006.gif" alt=截图.png></span></p>

<p class=MsoNormal><span style='font-size:
10.0pt;font-family:"Verdana","sans-serif";background:white'>可变头部</span>
</p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>协议名称和协议版本都是固定的。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>连接标志<span lang=EN-US>(Connect Flags)</span></span>
</p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>一个字节表示,除了第<span lang=EN-US>1</span>位是保留未使用,其它<span
lang=EN-US>7</span>位都具有不同含义。</span></p>

<p class=MsoNormal style='line-height:102%'><span
style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>业务上很重要,对消息总体流程影响很大,需要牢记。</span></p>

<p class=MsoNormal style='line-height:102%'><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>Clean Session</span>
</p>

<p class=MsoNormal style='line-height:102%'><span
lang=EN-US style='font-size:10.0pt;line-height:102%;font-family:"Verdana","sans-serif";
background:white'>0</s

Tags: mqtt, 协议分析

Related Posts:

2 Comments »

  1. lidashuang

    现在用这个吗

Leave a Comment