MQTT uses a TCP/IP connection. This connection is normally left open by the client so that is can send and receive data at any time.
If no data flows over an open connection for a certain time period then the client will generate a PINGREQ and expect to receive a PINGRESP from the broker.
This message exchange confirms that the connection is open and working
This period is known as the keep alive period.
This is what the specification says:
The Keep Alive is a time interval measured in seconds. Expressed as a 16-bit word, it is the maximum 529 time interval that is permitted to elapse between the point at which the Client finishes transmitting one 530 Control Packet and the point it starts sending the next. It is the responsibility of the Client to ensure that 531 the interval between Control Packets being sent does not exceed the Keep Alive value. In the absence of 532 sending any other Control Packets, the Client MUST send a PINGREQ Packet [MQTT-3.1.2-23]. 533
The Client can send PINGREQ at any time, irrespective of the Keep Alive value, and use the PINGRESP 535 to determine that the network and the Server are working.
The default keep alive period for the Python MQTT client is 60 secs, but it can be set to anything you want when you establish the client connection.
The connect function can be called with 4 parameters as shown below :
connect(host, port=1883, keepalive=60, bind_address=””)
Note: When using the Python MQTT client you don’t normally need to generate these ping messages as they are taken care of by the client when you call the loop() function.
Viewing Client PINGREQ and PINGRESP Messages
You can view these ping requests and responses on the server and client.
To view on the server start mosquitto with the verbose option or enable logs- see Mosquitto logging and logs.
Here is a screen shot of the server console with retry period set to 20 seconds.
To view on the client use the on_log callback.
def on_log(client, userdata, level, buf): print("log: ",buf) client.on_log=on_log # set client logging
The screen shot below shows the output of a client script that is connected to a broker, but doesn’t send or receive any messages.
You can see that the PINGREQ and PINGRESP messages.Here is a screen shot of the client.
You may think that sending messages on a regular basis would stop the PING messages but it turns out that the keep alive interval applies to both publish and receive messages.
Below is a screen shot with the client publishing at regular intervals( every 5 seconds) but pings are being sent (keep alive is 12 secs).
If I modify the test script by subscribing to the same topic so I receive messages, as well as publish messages, you notice that no PINGREQ and PINGRESP are being sent.
In the absence of send and receive messages if for some reason the PING requests/responses aren’t successful then the broker will force disconnect the client.
I have modified the script to include a simple timer and set the keep alive to 6 seconds.
This is what the specification says should happen in these circumstances:
If the Keep Alive value is non-zero and the Server does not receive a Control Packet from the Client 538 within one and a half times the Keep Alive time period, it MUST disconnect the Network Connection to the 539 Client as if the network had failed [MQTT-3.1.2-24].
When I run the script this is what I see:
You can see that the server disconnects the client after approx 9 seconds.
Here is the MQTT Keep Alive video on YouTube
Common Questions and Answers
Q-Can I disable Keep alive messages?
A- Yes set the keepalive to 0
Q- Does it make sense to have a very long keep alive period?
A- Personally if I was expecting that a client would have very long periods (>15mins) of total inactivity I would disconnect it, and reconnect when It had data to send..
Related Tutorials and Resources
- Understanding the MQTT Client object
- MQTT Client Connections with Examples
- Understanding The loop
- Understanding Callbacks.
- MQTT Subscribe-Python MQTT Client Examples
- MQTT Publish-Python MQTT Client Examples