UDP Pong - Protocol Design
There's a lot more we have to do here than in the UDP File Transfer app. By design UDP is connectionless, but the problem is that we need to have our clients to be able to establish a connection, maintain it, transfer data in between, and then quit when they want. We'll be implementing these things ourselves.
Basic Packet Structure
The first four bytes of each packet will denote its
PacketType. Instead of encoding some ASCII bytes like we did with the File Transfer example we'll be using 32 bit unsigned integers (4 bytes). The next eight bytes will be a
Timestamp encoded in a signed 64 bit integer (8 bytes). After that will be the
Payload, it's just an array of bytes. It can be empty or it might have something to it. That all depends on the
PacketType. So at minimum all
Packets will be 12 bytes long.
Types of Packets
Here is what each
PacketType is, with a description:
RequestJoin- Sent by the Client to the Server requesting to join a game.
AcceptJoin- Sent by the Server to the Client as a response to the above. It contains which
Paddlethe Client will be.
AcceptJoinAck- Sent by the Client the Server to acknowledge the above.
Heartbeat- Sent by the Client to the Server to notify its still connected.
HeartbeatAck- Sent by the Server to the Client to acknowledge the above.
GameStart- Sent by the Server to the Client to notify the game is going to start.
GameStartAck- Sent by the Client to the Server to acknowledge the above.
PaddlePosition- Sent by the Client to the Server to tell its
Paddle's current position.
GameState- Sent by the Server to the Client to tell it the current state of the game (
PlaySoundEffect- Sent by the Server to the Client to play a sound effect.
Bye- Sent by either the Server or the Client to notify the other it's done with the game.
This is our version of the TCP Three-Way Handshake. The Client will send a
RequestJoin to the Server. The Server will respond with an
AcceptJoin message; it is the only one that contains data (an unsigned 32 bit integer that denotes the Client's
Paddle). Then the Client will need to respond with the
AcceptJoinAck. Here is a diagram of the handshake:
Maintaining the Connection
This is pretty simple, the client will send
Heartbeat messages and the server will send back
HeartbeatAck messages in response. The Client and Server will also record the times they got them and use it to determine if a connection has dropped or not. The heartbeat timeout value will be 20 seconds. These are sent after a connection has been established, while waiting for a
GameStartAck, and while the game is being played.
The Server will not start the game until two Clients are connected. Once that criteria has been met, it will send out the
GameStart messages. The Clients will both need to respond with a
GameStartAck before the Server will deliver any
A few times per second both the Clients and the Server will send each other info about their current state. The Client only needs to send
Packets; it contains one floating point number that is the
Paddle's Y position. The Server will send a
Packet to both Clients. It will contain the
Ball positions as well as the scores (see the diagram below for the data layout). Periodically the Server will send a
PlaySoundEffect message. This will tell the Client it should play a sound effect. The name of the sound effect is encoded as a UTF-8 string.
Check the code for
Packet.cs for details, specifically the classes
PlaySoundEffect. They will show you how the data is laid out.
Ending the Connection
At any time a Client or Server could send a
Bye. This simply tells the other that the connection is over. If a Client sends it to the Server while in the middle of a game, the Server then needs to notify the other client the game is over. When the Server shuts down, it should send a
Bye message to all connected Clients.