/reliable-udp

.NET library that implements reliable (and optionally ordered) UDP delivery.

Primary LanguageC#MIT LicenseMIT

Tests

ReliableUdp

.NET library that implements reliable (and optionally ordered) UDP delivery. The design is inspired by Gaffer on Games article: https://gafferongames.com/post/reliable_ordered_messages/. Since the library targets the .NET Standard 1.0 any .NET project using any framework is supported including Unity 2018.1 and up.

The library guarantees that messages are:

  • sent reliably (individual message can be optionally sent unreliably)
  • received without duplicates
  • received in order (optional)

❗ When using this library it is vital that the client and server both use this library to send and receive messages.

The library does not exercise head of line blocking in the traditional sense, but rather re-sends messages until a confirmation (ack) of their receival has been received. Messages are sent again after the previous sent time + RTT has passed. This could in theory lead to duplicate messages, but the library sorts those cases out. More recent messages are still continously sent and when received they're buffered and made available once the previous lost message has arrived.

⚠️ When the library is used to receive messages in order a delay occurs for all reliable messages that arrive after a lost message should've arrived until the lost message was sent again and received successfully. The delay is usually equal to the length of the RTT. If this behavior is not acceptable, the library can provide messages immediately when they have been received (while keeping them reliable) which can lead to them not being in the same order as they have been sent in.

In addition to the above the library provides an interface to serialize/deserialize messages and handles packing messages together into packets. A packet containing multiple messages is kept under 508 bytes (can be configured differently). This is due to the MUT of the ip protocol to decrease the occurance of packet fragmentations and therefore decrease the chance of losing a packet (a missing fragment of a ip packet will cause the entire ip packet to be dropped). 508 bytes is chosen because it leaves enough room for a potentially expanded ip header to support IPv6 and routers adding aditional data to the header. Bigger messages than 508 bytes can be transmitted too, but will be sent in a separate packet without other messages packed into the same packet. No additional action for this has to be taken by the user of this library to make it work. Bigger messages have the same reliability, in-order and deduplication guarantees as smaller packets, but can result in higher packet loss ratios. The overhead for each packet is 8 bytes per packet (see PacketHeader) and 5 bytes per message (see BaseMessage).

The library strives for high quality by:

  • keeping the library code clean and simple
  • no external third-party dependencies (see .csproj file)
  • testing broadly with unit- and integration-tests cross-platform
  • limiting feature-set to bare needed minimum
  • implementing a clear and easy to use API
  • providing good documentation and examples

Roadmap:

  • Reliable ordered delivery
  • Add examples
  • Support for unreliable messages
  • Support for unordered message receival
  • Support for raw buffers (not using built-in serialization/deserialization system)
  • Retransmission based on RTT (flood control)
  • Optimize memory allocation
  • DTLS support