MQTT-Java CONNECT协议之重连

147 阅读11分钟

目标

理解客户端在断开连接后的CONNECT重连协议

准备

参见 “MQTT 实践” ,“MQTT-Java 连接协议” 完成测试工程配置

实验场景步骤

  1. 客户端连接服务端
  2. 客户端订阅主题
  3. 客户端断开连接
  4. 客户端停留10秒
  5. 客户端重连服务端
  6. 通过MQTTX 发布一个主题为"harvey",内容为“连接成功了”的信息
  7. 客户端收到主题为“harvey”的"连接成功了"消息

实验代码

/**
 *
 * 客户端连接 & 订阅主题 & 客户端断开 & 重新连接
 *
 */
private static void subscribeAndDisconnectAndReConnect(){
    MemoryPersistence persistence = new MemoryPersistence();

    try {
        MqttConnectionOptions connOpts = new MqttConnectionOptions();
        connOpts.setCleanStart(false);
        connOpts.setKeepAliveInterval(0);
        connOpts.setSessionExpiryInterval(60L);
        MqttAsyncClient sampleClient = new MqttAsyncClient(MQTTConfigue.broker, MQTTConfigue.clientId, persistence);
        IMqttToken token = sampleClient.connect(connOpts);
        token.waitForCompletion();

        subscription(sampleClient);

        IMqttToken iMqttToken = sampleClient.disconnect();
        iMqttToken.waitForCompletion();

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        try {
            sampleClient.reconnect();
        } catch (MqttException e) {
            HarveyDebug.d(e.getMessage());
        }

    } catch(MqttException me) {
        System.out.println("reason "+me.getReasonCode());
        System.out.println("msg "+me.getMessage());
        System.out.println("loc "+me.getLocalizedMessage());
        System.out.println("cause "+me.getCause());
        System.out.println("excep "+me);
        me.printStackTrace();
    }
}

客户端连接MQTT服务器日志

2023-08-29 15:51:28:206 Send 包类型:CONNECT
2023-08-29 15:51:28:208 Send Message Header(二进制内容) : 00010000 00100111 00000000 00000100 01001101 01010001 01010100 01010100 00000101 00000000 00000000 00000000 00000101 00010001 00000000 00000000 00000000 00111100 
2023-08-29 15:51:28:208 Send Message Header(字符串内容) : '�MQTT������<
2023-08-29 15:51:28:209 Send Message payload(二进制内容) : 00000000 00010101 01001001 01101110 01110100 01100101 01001001 01001001 01101001 01001010 00100000 01001001 01000100 01000101 01000001 00100000 01000011 01101100 01101001 01100101 01101110 01110100 00100000 
2023-08-29 15:51:28:209 Send Message payload(字符串内容) : 内容长度=23,内容=�InteIIiJ IDEA Client 

2023-08-29 15:51:28:211 Receive 包类型:CONNACK
2023-08-29 15:51:28:213 Receive Message Header(二进制内容) : 00100000 00001100 00000000 00000000 00001001 00010011 11111111 11111111 00100001 00000000 00010100 00100010 00000000 00001010 
2023-08-29 15:51:28:213 Receive Message Header(字符串内容) :  ��	��!�"�

2023-08-29 15:51:28:213 Receive Message payload(二进制内容) : 
2023-08-29 15:51:28:214 Receive Message payload(字符串内容) : 

2023-08-29 15:51:28:220 Send 包类型:SUBSCRIBE
2023-08-29 15:51:28:220 Send Message Header(二进制内容) : 10000010 00001100 00000000 00000001 00000000 
2023-08-29 15:51:28:220 Send Message Header(字符串内容) : ��
2023-08-29 15:51:28:221 Send Message payload(二进制内容) : 00000000 00000110 01101000 01100001 01110010 01110110 01100101 01111001 00000001 
2023-08-29 15:51:28:221 Send Message payload(字符串内容) : 内容长度=9,内容=�harvey

2023-08-29 15:51:28:221 Receive 包类型:SUBACK

2023-08-29 15:51:28:222 Receive Message Header(二进制内容) : 10010000 00000100 00000000 00000001 00000000 
2023-08-29 15:51:28:222 Receive Message Header(字符串内容) : ���
2023-08-29 15:51:28:223 Receive Message payload(二进制内容) : 00000001 
2023-08-29 15:51:28:223 Receive Message payload(字符串内容) : 

2023-08-29 15:51:28:224 Send 包类型:DISCONNECT
2023-08-29 15:51:28:224 Send Message Header(二进制内容) : 11100000 00000010 00000000 00000000 
2023-08-29 15:51:28:224 Send Message Header(字符串内容) : ���
2023-08-29 15:51:28:225 Send Message payload(二进制内容) : 
2023-08-29 15:51:28:225 Send Message payload(字符串内容) : 内容长度=0,内容=
2023-08-29 15:51:38:336 start connect remote server : 127.0.0.1:1883

2023-08-29 15:51:38:652 Send 包类型:CONNECT
2023-08-29 15:51:38:652 Send Message Header(二进制内容) : 00010000 00100111 00000000 00000100 01001101 01010001 01010100 01010100 00000101 00000000 00000000 00000000 00000101 00010001 00000000 00000000 00000000 00111100 
2023-08-29 15:51:38:652 Send Message Header(字符串内容) : '�MQTT������<
2023-08-29 15:51:38:653 Send Message payload(二进制内容) : 00000000 00010101 01001001 01101110 01110100 01100101 01001001 01001001 01101001 01001010 00100000 01001001 01000100 01000101 01000001 00100000 01000011 01101100 01101001 01100101 01101110 01110100 00100000 
2023-08-29 15:51:38:654 Send Message payload(字符串内容) : 内容长度=23,内容=�InteIIiJ IDEA Client 

2023-08-29 15:51:38:655 Receive 包类型:CONNACK
2023-08-29 15:51:38:655 Receive Message Header(二进制内容) : 00100000 00001100 00000001 00000000 00001001 00010011 11111111 11111111 00100001 00000000 00010100 00100010 00000000 00001010 
2023-08-29 15:51:38:656 Receive Message Header(字符串内容) :  �	��!�"�

2023-08-29 15:51:38:656 Receive Message payload(二进制内容) : 
2023-08-29 15:51:38:656 Receive Message payload(字符串内容) : 

2023-08-29 16:00:52:193 Receive 包类型:PUBLISH
2023-08-29 16:00:52:197 Receive Message Header(二进制内容) : 00110010 00011010 00000000 00000110 01101000 01100001 01110010 01110110 01100101 01111001 00000000 00000001 00000000 
2023-08-29 16:00:52:198 Receive Message Header(字符串内容) : 2�harvey��
2023-08-29 16:00:52:198 Receive Message payload(二进制内容) : 11101000 10111111 10011110 11100110 10001110 10100101 11100110 10001000 10010000 11100101 10001010 10011111 11100100 10111010 10000110 
2023-08-29 16:00:52:199 Receive Message payload(字符串内容) : 连接成功了

2023-08-29 16:00:52:216 Send 包类型:PUBACK
2023-08-29 16:00:52:216 Send Message Header(二进制内容) : 01000000 00000010 00000000 00000001 
2023-08-29 16:00:52:217 Send Message Header(字符串内容) : @�
2023-08-29 16:00:52:217 Send Message payload(二进制内容) : 
2023-08-29 16:00:52:217 Send Message payload(字符串内容) : 内容长度=0,内容=

MQTT 协议规范对照解析

MQTT 协议结构

整体结构 :固定头+可变头+内容 
协议-包结构.png

协议发生流程

第一步第二步第三步第四步第五步第六步第七步第八步
CONNECTCONNACKSUBSCRIBESUBACKCONNACKCONNACKPUBLISHPUBACK
连接连接ACK订阅订阅ACK连接连接ACK接收发布主题回复发布主题ACK

CONNECT协议详细解析

连接协议Header对比

通过对比,发现客户端在使用reconnect()方法重新连接时,固定请求头没有区别

场景固定头类型剩余长度协议名协议版本号连接标识位连接保活时间属性长度属性:session有效期session有效期值
第一步Header000100000010011100000000 00000100 01001101 01010001 01010100 01010100000001010000000000000000 00000000000001010001000100000000 00000000 00000000 00111100
第五步Header000100000010011100000000 00000100 01001101 01010001 01010100 01010100000001010000000000000000 00000000000001010001000100000000 00000000 00000000 00111100