eclipse / paho.mqtt.python

paho.mqtt.python
Other
2.19k stars 722 forks source link

PINGREQ still going out even when QoS 1 publishes are happening within keep alive period #813

Open tsturzl opened 7 months ago

tsturzl commented 7 months ago

Prerequisites

Note: You may remove this section prior to submitting your report.

A small team of volunteers monitors issues. Please help us to help you by making it simple to understand and, if possible, replicate your issue. Prior to reporting a bug please:

Bug Description

I have a client configured for a 4 second keep alive, and I'm publishing QoS 1 messages every 500ms. I still see PINGREQ going out in a packet sniffer. This means that keep alive is making unneeded ping requests. This doesn't track the behavior the documentation seems to suggest, nor does it seem to resemble the behavior of other clients such as the paho.mqtt.java client. Obviously this isn't a major behavior issue, but we noticed this behavioral difference while packet sniffing python and Java clients, and it seems python is the outlier in terms of behavior, especially since the documentation seems to suggest that keep alive should only ping in absence of other control messages.

Reproduction

I'll just provide a test script:

import paho.mqtt.client as mqtt
import time

client = mqtt.Client()

def on_disconnected(_client, _userdata, _rc):
    print("DISCONNECTED")

client.on_disconnect = on_disconnected

# enable logging, let it create it's own logger
client.enable_logger(logger=None)

print("connecting...")
client.connect("localhost", 1883, 5)
print("connected")
print("starting loop...")
client.loop_start()
print("loop started")
while True:
    print("publishing message...")
    client.publish("testtopic1", "hello world", qos=1)
    time.sleep(0.5)

Environment

Logs

Logs are largely irrelevant. I observed this in a debugger, ping is still happening even though publish QoS 1 is happening many times in the keep alive period.

langer-volt commented 3 months ago

Is your client subscribing to anything? I believe a long duration of no messages in could be triggering your PINGREQ

It's a logical OR that can be triggered if <msg_in_expired> OR <msg_out_expired> https://github.com/eclipse/paho.mqtt.python/blob/d45de3737879cfe7a6acc361631fa5cb1ef584bb/src/paho/mqtt/client.py#L3271

tsturzl commented 3 months ago

I don't believe we need to be subscribed on anything. Doing the exact same thing I Java results in no PINGREQ being sent. QoS 1 will always have a PUBACK on success, so it should be enough to prove the connection is open and functional bidirectionally.