8000 Reset the last ping time only after a ping is sent, rather than after… by bgreco · Pull Request #5 · php-mqtt/client · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Reset the last ping time only after a ping is sent, rather than after… #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 19, 2020

Conversation

bgreco
Copy link
Contributor
@bgreco bgreco commented Jun 18, 2020

Using php-mqtt v0.1.2 as a subscriber, and mosquitto v1.4.15 as the broker:

Whenever the client receives a command from the broker, it resets its internal "last ping" time. If these commands are received frequently enough, the "last ping" time never exceeds the keepalive value, so pings are never sent, causing the broker to report the client has timed out and close the connection. I get a message like this in the mosquitto log:

Client myclientid has exceeded timeout, disconnecting.

And the client throws an exception soon after:

PHP Fatal error:  Uncaught PhpMqtt\Client\Exceptions\DataTransferException: [65] Transfering data over socket failed: Sending data over the socket failed. Has it been closed? in /home/brad/temp/job_processor_mqtt/vendor/php-mqtt/client/src/MQTTClient.php:1308

Not having read the MQTT spec, I don't know if this is a bug in the client or the broker. I was able to fix it by only resetting the last ping time after a ping is sent, rather than after every broker command is received.

… any broker command is received. If broker messages are received too frequently, it causes pings to be never sent and the broker disconnecting the client.
@Namoshek
Copy link
Collaborator

Thank you for the PR, it looks like this could be related to #4.

On the one hand, I think the current implementation of the client adheres to the specification as it can be found here for example (see sub-section Keep Alive Timer). On the other hand, I cannot imagine a widely used broker like Mosquitto comes with such a severe bug, since a lot more people and pieces of software would experience issues then. In other words, I'm clueless.

I'll have a more thorough look at this tomorrow though, maybe looking for some other specifications. I also used the v3 specification during development, which states the exact same thing as the v3.1 spec. At least that's what I understand from it:

The Keep Alive timer, measured in seconds, defines the maximum time interval between messages received from a client. It enables the broker to detect that the network connection to a client has dropped, without having to wait for the long TCP/IP timeout. The client has a responsibility to send a message within each Keep Alive time period. In the absence of a data-related message during the time period, the client sends a PINGREQ message, which the broker acknowledges with a PINGRESP message.

@Namoshek
Copy link
Collaborator

I also found an article in the HiveMQ blog which interpretes the quoted spec the same way I did. And with HiveMQ the client works fine. I need to investigate this further...

@Namoshek
Copy link
Collaborator

I think I understand the problem now. You are subscribing and publishing messages with QoS = 0, which means the client does not send an acknowledgement for messages received for its subscriptions. When such a QoS = 0 message is received, the client resets its ping timer, thinking it is the last time it heard from the broker.

The problem with that is that even though the client heard from the broker, the broker hasn't heard from the client, since no acknowledgement is being sent. Therefore the broker kills the connection after the configured Keep Alive Interval.

In order to fix this, we simply reset the ping timer only when data is sent to the broker, but not when data is received. This is best done in the writeToSocket() method. Hope this works for you!

@Namoshek Namoshek merged commit e4b5f47 into php-mqtt:0.1 Jun 19, 2020
@bgreco
Copy link
Contributor Author
bgreco commented Jun 23, 2020

Thanks a lot for looking into this! Your explanation makes perfect sense and I'm no longer seeing the issue in v0.1.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0