MQTT Keep Alive Interval Explained With Examples

mqtt-keep-aliveMQTT 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
534
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.

mosquitto-console-client-pings

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.

python-client-pings

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).

client-pings-1

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.

client-pings-2

Failed Connections

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.

More importantly I have suppressed the PINGREQ message so the broker never sees it.

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:

client-pings-3

You can see that the server disconnects the client after approx 9 seconds.

Video- MQTT Keep Alives Explained

Common Questions and Answers

Q – Can I disable Keep alive messages?

A- Yes set the keep alive 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

 

 

Save

Save

Please rate? And use Comments to let me know more

32 comments

  1. Hi Sir,

    I have client (C++ )application running on Windows 10 using Paho Client Lib. When I block the IP Address of my broker (In Windows Defender Firewall) I have defined rules for Inbound and Outbound, After blocking still KeepAlive interval I am receiving the messages from Broker. Later I am not receiving any messages.

    So how can I stop immediately sending and receiving messages temporarily without disconnecting the MQTT client.

    1. The easiest method is to stop the loop which means that the client doesn’t see the ping response from the server and the server will then disconnect as the client will ping again.
      Rgds
      Steve

  2. Hi Steve! I have just started to work with mqtt now but I have a problem and I think it is due (maybe I don’t know) to “Keep Alive Internal”.

    I am using an Arduino MKR Wifi 1010 client which continuously transmits every ~ 2 seconds to a Raspberry client (The broker is also the raspberry).

    When I start my system everything is fine but after 15-20 minutes my raspberry client is not receiving anything. Do you think it’s due to “Keep Alive Internal” or something? If you can help me it will save me

    1. It could be the keep alive check for transmit and receive messages. So even though you are transmitting as you are not receiving the keep alive should be triggered.
      Do you see any keep alive messages on the broker.
      Try setting the keep alive to 30 mins and see if that has any impact or set to 0 to disable it.
      Rgds
      Steve

  3. Hi Steve, I got some problem with MQTT behavior.

    My situation is: When set KeepAlive time to 10s for example, and my MQTT Client is publishing data {qos:0} every 1s, which means there should be no PINGREQ from Client. Then, Broker only expects to close connection after 10*1.5 secs, so does Client.

    But if the connection is down in no-more-than 10s, I don’t know why but the Client still keeps sending data without recognizing there’s no internet connection. And then when the internet connection is back, because time doesn’t exceed KeepAlive, both Client and Broker will keep using the same TCP connection => All data that were published in no-internet time will be flush to Broker ( I think they were queued/stuck).
    If down connection occurs more than KeepAlive => new connection is setup, no on-flying/queued message found.

    Since I don’t want to receive any old data, I tried everything to dispose all queued message ( disable queueQoSZero, etc … ) but nothing worked. The only solution I think is set small KeepAlive time (currently I set to 10s already) , if smaller, Client and Broker will expect disconnect/reconnect so many time, which may cause instability.

    Have you experienced anything like this. Please teach me if there’s any solution for this problem. I would really appreciate. Thank you in advance! and if you don’t mind, let me discuss with you further by email.

    1. How do you know the connection is down? What Qos are you using to send? What client are you using?

  4. Hi Steve,
    What should be the keep alive value for a client which will receive data at highly irregular time intervals, may be minutes or maybe hours.

    1. There is really no right answer. A client that sends and receives data frequently never goes over the default 60s period and so no extra network traffic is generated. For a client that sends and receives infrequently then most of the traffic will be keep alive ping messages.
      So i you aren’t worried about this extra network traffic I would stay with the default as it means that after 60s a failed connection will be detected if you increase the period then it will possibly take longer to detect this.

  5. Hi steve, can I keep timeout-connection continuously? My problem is that I use SIM800 to send connect, pub/sub packet to cloudmqtt. All are ok, but connection only keep about 4 minutes ( I set KEEP-ALIVE is 4B), cuz I want SIM800 keep connection to server to subscribe message from server, How can I do that? My present solution is checking connection and reconnect if server disconnect to sim800. Can you recommend me a solution? I appreciate your reply.

    1. Can you explain further. The keep alive is a network check does the client on the SIM800 support keep alives? If not set it the interval to 0 and it should work.
      Rgds
      Steve

  6. Dear Steve,
    Thanks for amazing website.
    I add keepalive, but does not work.

    broker=”test.mosquitto.org”
    #define callback
    def on_message(client, userdata, message):
    time.sleep(1)
    print(“received message =”,str(message.payload.decode(“utf-8”)))

    client= paho.Client(“client-001”) #create client object client1.on_publish = on_publish #assign function to callback client1.connect(broker,port) #establish connection client1.publish(“house/bulb1″,”on”)
    ######Bind function to callback
    client.on_message=on_message
    #####
    print(“connecting to broker “,broker)
    client.connect(broker,keepalive=2000)#connect
    client.loop()
    print(“subscribing “)
    client.subscribe(“house/bulb1”)#subscribe
    print(“publishing “)
    client.publish(“house/bulb1″,”on”)#publish

    client.disconnect() #disconnect

    can you tell me what can I do?
    thanks

    1. Hi
      Not sure how you are testing. You have set the keepalive to about 33 minutes so you have to wait that long to see a ping and it looks to me like your script stops after publish as I don’t see any holding loop.
      Rgds
      Steve

  7. I have installed and use a locally installed mosquitto version 1.5.7 on a raspberry with default settings. The network is used by various devices as mqtt clients and everything seems to work fine. Arduino and esp8266 work with pubsubclient lib.

    Now I have introduced a new bare bone Arduino (ATMEGA328P-PU) with a mini W5500 ethernet breakboard as client. Things again work fine, it connects, sets static IP, publishes and subscribes.

    However it is unable to keep the connection live after some time. I have tried to play with MQTT_KEEPALIVE, but still PINGREQ & PINGRESP messages are not exchanged between client and broker and so the connection is dropped by broker.

    Any suggestions as to what to look for or try? Also is client.loop() responsible for these pings that are not exchanged?

    Many thanks!

  8. Helo Steve,

    I have integrated the MQTT in one of my recent project. The only problem i am receiving right now that i am sending user location on the 30 seconds basis but when in the low internet connection or network switch broker shut down the connection and but client is trying to reconnect with the same client id in and gives me error at client side “Software cause connection abort” and at the broker side the connection is closed. What should i do in this situation?
    My keep alive time period is 5 mins.

  9. Hi Steve
    i need your help on my basic mqtt setup ,kindly help me on this.
    i have publish the 1500 message through the broker, but at receiving side i am able to get only 1332 messages through subscribing the topics.
    not Sure why its happening,
    Kindly help me on this ?

    1. Difficult to say as there are so many unknowns.what client are you using? Is it a cloud broker or local? What is the message rate are they arriving at the broker etc
      You need to check all of these individually.

  10. Steve, thanks for this tutorial. One question, I was developing some mqtt projects with Arduino and the mqtt library, however I could not make the callback function to work with a gars interface. Now, the actual question is about the use of the ping messages to make sure the connection is up, or better said, to detect that the connection was down and has to be re-established (reconnect). is there any way to have feedback of the ping response not received so based on this to re-connect? thanks again.
    Luis

    1. Yes it’s a timeout so you just time the ping responses and if not received after 1.5*keep-alive then the connection is down.

  11. Hi Steve,

    My problem is that the last will is send by the broker but the client is not disconnected and accepts the next call. Probably a slow wifi connection. Problem is that subscribed clients think it is dead ( received last will ) but as the client does not need to reconnect it does not send a ‘connected’ (sent immediately after a connect) message.

    Keep alive = 15 seconds, issued by esp8266
    Server = mosquitto.

    Would the keepalive set to 30 seconds be better? I would like the value to be at least 2 pings further, but in the docs it says 1.5 times keep alive sends last will. Can i change the ping interval? Something like: pin every 20 seconds, keep alive 60 seconds. Thus 3 lost pings means we’re probable dead…

    Regards,
    Henk

  12. Hi Steve,
    I am trying to teach my students the force disconnect state. Can you share how you were able to suppress the pinreq?

    1. Hi
      It’s been a while since I did it but I think that I commented out the line in the pingreq function in the client.py module

      rc=self._send_simple_command(PINGREQ) but you need to set it as you will get an error on the next line
      def _send_pingreq(self):
      self._easy_log(MQTT_LOG_DEBUG, “Sending PINGREQ”)
      rc = self._send_simple_command(PINGREQ)
      if rc == MQTT_ERR_SUCCESS:
      self._ping_t = time_func()
      return rc

      def _send_pingresp(self):
      self._easy_log(MQTT_LOG_DEBUG, “Sending PINGRESP”)
      return self._send_simple_command(PINGRESP)

      Rgds
      Steve

      1. Hi Steve,
        Thanks a lot. I was able to acheive similar result, by editing soucrrce code of Pubsubclient.cpp by nickoleary, for my esp32.

        Now i can simulate the condition for my students to learn
        Thanks

  13. hi can u tell me that when we use pingreq and we get pingres do value of keepalive reset and the connection will not brake

    1. The pingreq/response don’t stop the connection breaking but only detect a broken connection.
      Are you worried about the keepalive value?

  14. “…If for some reason the PING requests/responses aren’t successful then the broker will force disconnect the client.” — you mean AND if other control messages have not been received, right? That is, PINGREQ/PINGRESP messages are sent only in absence of other messages — if PUBLISH messages were regularly sent, there would be no need for PINGs at all.

    Also: “…. the keep alive interval applies to both publish and receive messages” — Do you mean: The same KeepAlive timer for PING[REQ|RESP] is set after after the client sends a PUBLISH message, after which a PINGREQ is sent? (not sure what you mean by RECEIVE; maybe you mean PUBREL when QoS=2?).

    1. Yes correct you only get ping messages if no other messages have been sent and received.
      By receive I mean that even if you have a client publishing messages continuously the Ping messages will be sent if the client isn’t receiving messages.

      I’ll amend the tutorial to make it clear

Leave a Reply to tan Cancel reply

Your email address will not be published. Required fields are marked *