Networking: ENet & Timeout Values, and the importance of heartbeats

Networking: ENet & Timeout Values, and the importance of heartbeats

ENet supports setting the timeout value on the connection. The way it’s formatted (as a enetpp:client_connect_params() parameter) makes it look like it only applies to the connection process:

client.connect(enetpp::client_connect_params()
.set_channel_count(1)
.set_server_host_name_and_port(address.c_str(), port)
.set_timeout(
static_cast<std::chrono::seconds>(3)));

As I found out, that’s not true. It applies to all data Rx and Tx (receive and transmit) actions- that means that the server and client must respond to any data received within the set timeout (in the case above, three seconds) otherwise it’ll disconnect.

What was the result of this? Many confusing moments where Wireshark was showing the client and server data Rx and Tx without any triggering of data sink functions (due to a one-line piece of code being in the wrong place). Unfortunately ENet will not raise an exception if you try and send data to a client that is no longer connected (it just ignores the data):

Fortunately after setting the timeout to 30 seconds, this was fixed. This also highlights the importance of game multiplayer heartbeat packets.
As an aside, the Flatline multiplayer system works perfectly over the Internet!

What’s a heartbeat?

A heartbeat is a packet that the client sends to the server periodically every few seconds to let the server know that it’s still there. This stops the above situation from happening where the server disconnects the client if the client does not send any data within a specific timeout timeframe.

This can be done via a simple update function every few seconds (in the Flatline networking spec, it’s 10) within the main game update function.

 

No Comments

Add your comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.