Advertisement

Reliable UDP messages

Started by February 18, 2015 06:38 PM
6 comments, last by Dave Weinstein 9 years, 9 months ago

"fire & forget" seems the best option for fast paced games, but even then there are messages which should be reliable - player connect/disconnect, player A headshot'ed player B, combat log or chat.

1) Is sending these messages "reliable way" best option? Syncing seems like wasting bandwidth. When data (eg. combat log) grows we will have to sync only newest part of data, which gives another layer of complexity and there is still possibility of loosing some data with bad connection quality.

2) Is sending messages in different delivery methods supported by most networking libraries? What I mean by that - are there any problems when sending 5 unreliable messages followed by 1 reliable? I am currently using lidgren but if someone has used other libraries I would gladly learn about them too.

Reliable transmission of data works by resending the data until the recipient informs the sender that it has arrived, regardless of whether it's TCP or UDP. There are different strategies controlling when resending occurs.

1) "Syncing" is implementation dependent, so it's not clear what you're concerned about.

2) You can do whatever the library is set up to do. Unreliable messages typically are not ordered, but may be marked with a timestamp of some kind to prevent processing an older update if two updates for the same object are received out-of-order. Reliable messages are usually ordered automatically by TCP or by the application layer, but don't always need to be.
Advertisement

I'm mostly familiar with Lidgren which is pretty much the one true networking library for .NET. It uses multiple "channels" where some channels are unreliable, others are ordered but may have packets dropped, others are reliable and ordered.

It will only resend those that are reliable. The unreliable option allows packets to be received out of order with some packets dropped etc. You can mix and match channels as you see fit for your various data types.

One way of doing "reliable" on top of "unreliable" is to repeat all information that should be reliable in each outgoing packet, until you get an acknowledgement for a packet that contains the reliable message. Typically, you will have a list of outgoing reliable messages, assign each a sequence number, as well as keep track of which messages were in which outgoing packets. When you get acknowledgement for a packet, remove all the outgoing reliable messages that were in that packet.

Note that the receiving end needs to be prepared to not double-handle reliable messages that it has already handled. Keeping a "last sequence number handled" variable and discarding messages with sequence numbers below that value is one way of doing so.
enum Bool { True, False, FileNotFound };

You can use dual connection - one for unreliable UDP, the other for reliable TCP.

If you are going to take making a reliable UDP, it's easy to end up with TCP or something similar to TCP(UDP with implementation of TCP).

If you turn off Nagle, TCP reaction time is fast enough that you can use it for an action game.

The biggest weakness with the paired TCP/UDP model (which was what was used in Rainbow Six, Rogue Spear, and the first Ghost Recon) is that it can't drill NAT for a consumer-consumer game, where a purely UDP based model can.

Advertisement

You can punch the hole with TCP as well, the only problem is it's going to be really hard job. and failure rate is higher then UDP.

So, yes, if you want to do P2P(client-client) direct communication. don't use TCP.

TCP-UDP combination is a suggestion for the client-server network model.

TCP-UDP with a client-server network model still works badly if the server is consumer hosted.

This topic is closed to new replies.

Advertisement