{"action":"created","issue":{"url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/187","repository_url":"https://api.github.com/repos/chkr1011/MQTTnet","labels_url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/187/labels{/name}","comments_url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/187/comments","events_url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/187/events","html_url":"https://github.com/chkr1011/MQTTnet/issues/187","id":300598546,"number":187,"title":"KeepAlive timeout interferes with normal message publish/receive","user":{"login":"pehachem","id":16595515,"avatar_url":"https://avatars1.githubusercontent.com/u/16595515?v=4","gravatar_id":"","url":"https://api.github.com/users/pehachem","html_url":"https://github.com/pehachem","followers_url":"https://api.github.com/users/pehachem/followers","following_url":"https://api.github.com/users/pehachem/following{/other_user}","gists_url":"https://api.github.com/users/pehachem/gists{/gist_id}","starred_url":"https://api.github.com/users/pehachem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pehachem/subscriptions","organizations_url":"https://api.github.com/users/pehachem/orgs","repos_url":"https://api.github.com/users/pehachem/repos","events_url":"https://api.github.com/users/pehachem/events{/privacy}","received_events_url":"https://api.github.com/users/pehachem/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-02-27T11:46:11Z","updated_at":"2018-03-02T11:05:11Z","closed_at":"2018-03-02T11:05:11Z","author_association":"NONE","body":"Hi Christian,\r\n\r\nI have a small test program that, using the regular MqttClient, rises \"_MQTT communication exception while sending/receiving keep alive packets._\" while processing a lot of publish/receive on the same connection. And connection is lost, of course.\r\n\r\nThe exception raised exactly 1 second (= CommunicationTimeout) after the log message \"_TX >>> PingReq [Timeout=00:00:01]_\"\r\nBetween both log messages, there are _a lot of_ other log messages from the client, reporting about the publish/listen traffic... and exactly one timeout period (same 100th of second).\r\n\r\nI think I found at least one cause.\r\n\r\nIf I force the Connection Timout to be large enough, then the exception is not raised and all messages are sent. Note that, on my core i7 under Win10 + VS2017, the test program publishes 1000 messages - Publish() _without awaitinng_ - to a broker, using MQTTS, and listen back to them from the broker at the same time.\r\n\r\nAs far as I understand your code, the keepalive timeout requires the server response to be _processed_ within one timeout. In this particular case, I think that MqttClient has not enough resources to ensure this delay... while the 'pong' message is in the deepth of the received message queue (in client or still in broker).\r\n\r\nNote that, as far as I understand the specification in MQTT, the keepalive handshake is required only if the connection has not been active in the past timeout period :-)\r\n\r\nHope this helps,\r\nPhilippe."},"comment":{"url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/comments/369892490","html_url":"https://github.com/chkr1011/MQTTnet/issues/187#issuecomment-369892490","issue_url":"https://api.github.com/repos/chkr1011/MQTTnet/issues/187","id":369892490,"user":{"login":"pehachem","id":16595515,"avatar_url":"https://avatars1.githubusercontent.com/u/16595515?v=4","gravatar_id":"","url":"https://api.github.com/users/pehachem","html_url":"https://github.com/pehachem","followers_url":"https://api.github.com/users/pehachem/followers","following_url":"https://api.github.com/users/pehachem/following{/other_user}","gists_url":"https://api.github.com/users/pehachem/gists{/gist_id}","starred_url":"https://api.github.com/users/pehachem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pehachem/subscriptions","organizations_url":"https://api.github.com/users/pehachem/orgs","repos_url":"https://api.github.com/users/pehachem/repos","events_url":"https://api.github.com/users/pehachem/events{/privacy}","received_events_url":"https://api.github.com/users/pehachem/received_events","type":"User","site_admin":false},"created_at":"2018-03-02T11:05:11Z","updated_at":"2018-03-02T11:05:11Z","author_association":"NONE","body":"Hi Christian,\r\n\r\nIf I understand well your suggestion, sending a ping at 1/10th of the keep alive period will let 14/10th of this period for the server to receive and process it (applying the '1.5x' rule for the server to close the connection). It will probably help - it is better than 5/10th - but it seems to me that you would get exactly the same time window if you directly multiply the keep alive period by 14/5th, without any code modification.\r\n\r\nI suggest another way to solve the issue:\r\n1 - Implement keepalive logic using retriggerable timers, were the delay is restarted by an external signal so that timeout would elapse only when there has been no signal activity in the past timeout delay:\r\n1.1 - On client side: timer should be retriggered every time a message has been sent (may safely include the sending of PINGREQ itself). When timeout finally occurs, a PINGREQ must be sent.\r\n1.2 - On server side: timer should be retriggered every time a PINGREQ has been received. When timeout occurs, the connection must be closed (server timeout value being 1.5x the client one).\r\n2 - On client side, there is an additional effort to do, since receiving PINGRESP is a health proof of the 2-ways connection.\r\nIt can be implemented like 1.2 is implemented on server side: a retriggerable timer may close the connection if no PINGRESP has been received after a 'reasonable' time the last PINGREQ has been sent. Note that the MQTT specification does not _require_ that the client disconnects in this case. Note also that a rule similar to the '1.5x' on PINGREQ should be applied, to take into account the transmission delays in both ways, and the processing delay on server. So I suggest to apply at least the '1.5x' rule; and why not '2x'?\r\n3 - Regarding the implementation, I suggest to implement this logic in a dedicated thread rather than as Tasks which would potentially wait for their turn to be scheduled in the thread pool. The reason is that these timing are real time constraints, and they are required to be as reliable as possible whatever be the task queue level.\r\n4 - while seeking the web on these issues, I found some interesting methods to implement retriggerable timers, like [this one](http://www.thomaslevesque.com/2015/06/04/async-and-cancellation-support-for-wait-handles/)\r\n\r\nWhat do you think of that?\r\nHope this helps,\r\nPhilippe.\r\n"}}
{"actor":{"display_login":"pehachem"}}