I'd like to make some small multiplayer games, so learning about UDP is a good place to start!

High-level Goal

At the end of this project I'd like to understand the basics of UDP connections in client-server configurations and have some sample code that I can use later.

Mid-level Goals

  • Build a simple client-server UDP demo for connections between LAN clients
  • Build a simple client-server UDP demo for connections between a client and remote server (possibly with NAT between them)
  • Build a multi-client-server UDP demo for connections between multiple clients and a remote server

Stretch Goals

  • Make a simple two-player game where game state is enforced by the server

Recent Activity

!til &junkworks And stretch goal has been reached! I've got my UDP client/server prototype controlling two characters. Clients send position packets to a server, the server forwards those packets to the clients, and the clients update the other character's position in space.

Next steps are to make state server-authoritative, implement client-side prediction, rollback, and interpolation. This has been a great jam. I learned a ton and have prototype code to build off of (cough cough refactor cough). Thank you @bvisness and all of the admin team for setting everything up!

!til &junkworks Awwww yeah, we've got client-server-client UDP action happening.

These two clients are running on the same Windows machine, but they're exchanging packets with a server in VA. The server forwards complementary packets to each client (client A gets client B's data, client B gets client A's data).

I can also throw in a third Linux client (A gets B and C data, B gets A and C data, C gets A and B data).

Next step is to hook this up to the renderer I've been working on and let some players run around.

!til &junkworks There are subtle and obnoxious API differences between Windows and Linux's implementations of recvfrom and sendto. Linux sends and copies buffers of void *, but Windows sends and copies buffers of char *. Linux uses size_t for the sizes of incoming and outgoing buffers; Windows uses int. Separate UDP socket implementations for both OS's might be worthwhile. That way you could include one or the other based on preprocessor directives rather than having preprocessor conditionals sprinkled over one implementation.

!til &junkworks You have to explicitly initialize sockets with a special function call on Windows before you can start binding to ports or sending bytes around. See "Initializing the socket layer" from here for reference.

!til &junkworks Clients behind NAT that want to receive data via UDP from a server outside of the NAT must first send a dummy packet to the server they want to hear back from. Also the server has to send its response to the same port as the client's dummy packet port. And the client still might not even receive the server's packet because NAT can choose to send the client's packet out on a different port that the port that was specified by the client. 😩 #necessarybutnotsufficient