Novice UDP Online Game Net Coding

Disclaimer, I’m not a low-level network coding expert, so I’m sure there are easier/better architectures for how to handle this sort of thing. I’ll study them someday

To keep my mind off the world going to shit recently, I redid parts of my game’s networking code last night to add “sync” support to my packet transmissions (make sure a packet was received).  Mini case study below.

Basically since UDP does not guarantee delivery of packets, packets can arrive late, never, out of order, or duplicated, you’re royally fucked if a certain important packet such as (the unit was split in two) arrives twice.  So for packets that aren’t just player position, you have to handle the sync properly.  Each packet starts with the same header

The first step is to add seq and ack to all outgoing packets where seq is the packet number of this packet and ack is the highest number of any packet we’ve received back.  For example, if the client is sending the 100th packet, seq will be 100.  If the server receives this packet, upon it’s next update to this client, it’ll send a packet with the ack containing 100, so the client can know it was received.  This is a super basic well known mechanism for reliability (TCP does something like this but considerably more complex)

So, the issue last night was, how the fuck do I handle a missed ack.  Architecturally it got a bit messy.  Basically my game works on a heartbeat type mechanism where the app is set into a certain state, (like a battle match), and the same packet type is sent over and over again from the client with updated data (the player positions).  If they get lost, no big deal, because another one is coming right away.  The receiver only considers the highest ordered seq packet, and disregards anything older than that.

For packets that must be received once and only once,
I had to start marking these critical packets as “sync” packets, meaning they are important and nothing else will be sent by the client until the server reports back that it got the sync packet, and that it successfully sync’ed it to every client connected to it.

The devil was completely in the details on doing this right.  For example, for a sync packet I had to ensure the seq number was the same during all retransmissions, so they would be processed only once, etc etc.

Key parts of this in the client are below (the server was considerably more complex, since it has to sync to multiple clients where the seqs/acks are different for each one)

..and the actual packet transmission code is below..

Currently, any ClientState (my packet base class) can set itself as a sync packet, once the Client encounters one of those, it’s in syncState mode (and retransmits the same packet over and over) until it’s resolved with an ack as shown above.  In the higher level game code, if the client is in a sync state, I treat the game as if it’s paused (can’t move).

..and lastly, the pertinent sections of the actual UDPConnection class follows below. This is where my game actually touches the OS sockets API. Generally, this API is the lowest level of networking programming available to most applications.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>