Reliable Packet Delivery
Reliable TCP sockets, for a variety of reasons, generally are considered unsuitable for game networking. Most of the reasons relate to how the sockets handle congestion and how they prioritize in-order delivery over timeliness. Most games use User Datagram Protocol (UDP) sockets, which means they send the vast bulk of their gameplay data unreliably. Reliable delivery, however, is still necessary for some data subsets. To improve reliablity, the XNA Framework provides a reliable delivery mechanism on top of UDP.
The XNA Framework SendData and ReceiveData methods are built over a reliable UDP packet layer. This packet layer provides optional ordering and delivery guarantees, as well as automatic packet coalescence (if several packets are sent in rapid succession) and splitting (if the payload is too big for a single UDP wire packet) to make efficient use of the underlying UDP channel.
Fundamentally, this is a peer-to-peer architecture with reliable connections from each machine to all other machines. However, this does not place any limitation on what topologies the game can use for its own network traffic. Client-server, peer-to-peer, or any kind of hybrid architecture can benefit from the reliable UDP protocol supported by the XNA Framework.
Packet Delivery Options and Network Performance
- Unreliable, out of order (SendDataOptions.None)
- Unreliable, in order (SendDataOptions.InOrder)
- Reliable, out of order (SendDataOptions.Reliable)
- Reliable, in order (SendDataOptions.ReliableInOrder)
- Chat data (SendDataOptions.Chat)
If a reliable, sequential message sent by using SendDataOptions.ReliableInOrder is dropped, later sequential messages cannot be delivered until the message is resent and received. In effect, this stalls the channel. If you use this option to send more messages, you will see real-world bottlenecks. If the receiver does not call ReceiveData quickly enough, or just stops altogether, the queue of messages to resend fills up.
Unreliable, sequential messages sent by using SendDataOptions.InOrder may have gaps in the sequence, but they will never go backward or stall because of previous non-reliable sequential messages. Unreliably sent data will not be resent. This is good for information such as player position that is updated frequently. Newer information will be available by the time the sender attempts to resend the data. For all game data that is sent—regardless of the delivery option— be sure to send the minimum amount of data necessary to communicate the information. This can be done by sending only changes in the game state rather than the entire game state.
For best performance in a network game, minimize the use of reliable and in-order packet delivery. In general, reliable packet delivery should be used only for data critical for your game to function properly because it consumes bandwidth resending packets as necessary.
SendDataOptions.Chat can be included independently of any other flags, and has two effects. First, any in-order chat sends are guaranteed only to be ordered with regard to other chat sends. There is no guarantee of ordering between non-chat and chat sends. Second, data within a chat send is unencrypted between the sender and receiver.