Network packet loss

Originally posted to Shawn Hargreaves Blog on MSDN, Friday, December 14, 2007

Networks are not reliable. When you send a data packet, many things can happen:

  1. It might arrive at the other end.
  2. It might never arrive.
  3. Packets might arrive, but in a different order to how you sent them.
  4. Packets might arrive, but their contents could be corrupted. Someone may have altered them along the way, trying to cheat or hack your machine.

That fourth problem is not an issue for XNA Framework games. Thanks to the underlying LIVE functionality, which automatically encrypts all network traffic, it is impossible to ever receive corrupted or tampered data.

The XNA Framework also provides optional solutions for problems 2 and 3, via the SendDataOptions.Reliable and SendDataOptions.InOrder flags. Why are these optional? Why wouldn't you always choose SendDataOptions.ReliableInOrder? While we're here, why don't games just use reliable TCP networking like everyone else?

The reason is that games are constantly updating a realtime simulation. Think about what happens behind the scenes when you send packets over a TCP channel, or using SendDataOptions.ReliableInOrder:

This works well for things like downloading a webpage. After all, there isn't much point delivering packet C, which contains the page footer, before you have packet A, which contains the HTML header and stylesheet reference: that just wouldn't make any sense.

But consider a game which is sending updated player positions at regular intervals:

How silly is that! If the game knows where the player was at time C, it is utterly irrelevant where they used to be at times A and B. It would be better to just skip over that old data and jump straight to the latest position.

When you combine SendDataOptions.ReliableInOrder with packet loss, you get increased latency. Without that flag, if a single packet gets dropped, there will be a minor glitch, after which the game can continue as normal. But with that flag, even a single dropped packet causes all subsequent packets to be delayed until the first one can be resent.

Note that when used separately, neither SendDataOptions.Reliable nor SendDataOptions.InOrder has this problem. It is only when you combine them both (asking for a TCP style behavior) that latency can be affected.

If you ask for reliable but unordered delivery, and packet A is dropped, then B delivered, the game gets to see B straight away. Packet A must be resent, but this need not delay the delivery of subsequent packets.

If you ask for ordered but unreliable delivery, a version number is included with every packet. If older packets arrive after a more recent one has already been received, the outdated ones are simply discarded. This is extremely cheap.

Shawn recommends:

Blog index   -   Back to my homepage