条目说明
库名paho.mqtt.c
版本1.3.12
githubhttps://github.com/eclipse/paho.mqtt.c.git
问题启用cleansessionautomaticReconnect后,连接中断恢复之后无法收到之前订阅的主题的消息。

问题原因

cleansessionautomaticReconnect被设置为1。

当连线中断恢复之后之前的session状态信息(QoS和订阅topic)被清空。

因此在MQTT客户端没有重新订阅的情况下,无法接收到消息。

解决方案

automaticReconnect和cleansession都不变

调用int MQTTAsync_setConnected (MQTTAsync handle, void *context, MQTTAsync_connected *co)设置MQTTAsync_connected回调函数。

在重新建立连接后在typedef void MQTTAsync_connected(void *context, char *cause)回调函数中重新订阅topic。

automaticReconnect不变

cleansession设置为0,可以确保重连之后session状态信息不会被清空,这样之前订阅的topic仍在,可以接收到消息。

cleansession不变

automaticReconnect设置0,然后在连线中断之后使用外部线程来重新建立连接,此时会重新订阅,接收消息。

相关资料

根据paho.mqtt.c的文档,MQTTAsync.h节选:

typedef struct
{
    /** The eyecatcher for this structure.  must be MQTC. */
    ...
    /**
     * This is a boolean value. The cleansession setting controls the behaviour
     * of both the client and the server at connection and disconnection time.
     * The client and server both maintain session state information. This
     * information is used to ensure "at least once" and "exactly once"
     * delivery, and "exactly once" receipt of messages. Session state also
     * includes subscriptions created by an MQTT client. You can choose to
     * maintain or discard state information between sessions.
     *
     * When cleansession is true, the state information is discarded at
     * connect and disconnect. Setting cleansession to false keeps the state
     * information. When you connect an MQTT client application with
     * MQTTAsync_connect(), the client identifies the connection using the
     * client identifier and the address of the server. The server checks
     * whether session information for this client
     * has been saved from a previous connection to the server. If a previous
     * session still exists, and cleansession=true, then the previous session
     * information at the client and server is cleared. If cleansession=false,
     * the previous session is resumed. If no previous session exists, a new
     * session is started.
     */
    int cleansession;
    /**
     * Reconnect automatically in the case of a connection being lost. 0=false, 1=true
     */
    int automaticReconnect;
    ...
} MQTTAsync_connectOptions;

cleansession

cleansession是一个boolean值,取值范围为0或1。

根据MQTT协议,当建立连接后MQTT客户端和服务器会共同维护一个session状态信息。该设置用于控制MQTT客户端和服务器在连接和断开时关于session的行为。

该session状态信息是为了确保消息按照QoS(至少一次、确定一次、最多一次)指定的方式接收,因此该session状态信息也包含了客户端建立的订阅topic。

cleansession=1时,session状态信息在连接或断开时会被丢弃;反之则会保留。

当使用MQTTAsync_connect()建立连接后,MQTT客户端会使用客户端ID和服务器地址来标识session,而服务器会检查是否有这个MQTT客户端的session信息(之前连接保存的):

  1. 如果session信息还在并且cleansession=1,则MQTT客户端和服务器都会清空之前的session信息;
  2. 如果session信息还在并且cleansession=0,则恢复之前的session;
  3. 如果没有该MQTT客户端对应的session信息,则新建session。

automaticReconnect

该参数指定在连线丢失之后是否会自动重连。

该参数取值范围为0或1,0表示不会自动重连,1表示会。