The code for this project can be found on GitHub here. When I reference points in code, I am using permalinks. As such, these links will reflect a specific point in time, and maybe not the most recent change.
Since I've decided to use Go as the language for the project, the standard library has built-in support for TCP and UDP networking out of the box. This makes things relatively easy to start implementing, the hard part is to get everything working correctly.
There needs to be three points-of-contact per client, a TCP socket hosted on the server where the client and the server can communicate any error corrections, a UDP socket hosted on the server to send game data, and a UDP socket hosted by the client so that the server can receive the client's current data. The problem is: how do we tell the server the client's UDP socket so that it can receive the game state of the client.
The solution ended-up being relatively simple. When the client starts, it does the following:
Spin up own UDP server - storing the auto-assigned port.
Connect to the server's UDP socket, sending the port of its own UDP server.
The server then connects using the remote IP address, and the port sent by the client.
The client then acknowledges this connection by the server, and sends its ready message so the server knows that it's ready.
The code relevant to this can be found in these points:
As we can see in the server code here, we send the message "Hello from server!" to the client, and we can see the message in the top left of the screen of the "game" (not a game yet).