Home | Schedule | Papers | Resources | Review Template | Project 1 | Project 2

Multiuser UDP Networking

Goals of the Project

The primary goal of this project is to teach you about network programming for games. A typical commercial game uses a client/server architecture. If we assume that UDP is going to be used, then the standard technique is to build it with a single server socket that uses select to test when the server socket is ready to be read from and written to. Note that you will still need to have multiple sockets to write to so that you can send data to individual clients.

While few games are built using a peer-to-peer architecture, graduate students will have the joy of building a peer-to-peer networking library based on NEO.

What to Do:

Undergrads

You are required to build a client/server architecture using UDP sockets. You've had practice in class, so you know how to actually create them and send data with them. All you have to do now is figure out how to write a protocol.

Protocols typically require several types of messages. For example, when you join a game, you often send a join game that contains your user ID. In addition, clients send commands to the server that indicate user input. Finally, the server sends update messages that tell each client what each other client is doing.

In this project, you need to write the networking code for the client and server. I don't expect you to write a game for this project, unless you already have one that you can network fairly easily. However, you do need to have at least the three message types indicated above.

Graduates

You will build a library to implement NEO. You have some freedom here in your implementation. From an application perspective, you have three functions:

Your functions or methods should be called something along those lines. At any point when the application has game data to send, it calls SendUpdate() with the data. You'll take that data and write it to each of the other peers. When your client is ready, it calls ReceiveUpdates() and any pending updates should be given to the application. To join a game, we call JoinGame() and give it the addresses of the other players in the game (we assume that we can bootstrap somehow and determine who those players are).

Note that NEO requires several steps. First, we send an update periodically, determined by the round length. Thus, we have to have a function to set the round length.

Next, NEO requires all clocks to be synchronized. For the purposes of this project, you can assume that this is the case, though normally the protocol would have to do this.

NEO first sends a cryptographically secure hash of the update in one round and follows it with the key in the next round. To do this, you may simply implement a random key to XOR the data with. The key size can be small (perhaps 64 bits). Note that this is insecure and NOT a good way to do this.

Finally, everyone must have an ID and we must vote based on those IDs for whether a packet was received in time. For this project, just assign an ID by the command line and you may assume the vote vector is in the order given by the counting order of the IDs.

To deal with the fact that we have to send updates, vote and determine which votes are valid, all without application input, I would suggest using a separate thread for the protocol.

Grading

Your project will be graded on the correctness of your implementation. Because I'm giving you freedom in your implementation, you may use any programming language you're most comfortable with, but it must be available for Linux and OSX to assist with my grading.

Extra Credit

If you actually use the serialization from Project 1 in Project 2 for sending and receiving updates, I'll award you up to 10 extra points, depending on the implementation. Note that you can't give me a broken or incomplete project that uses your serialization and expect extra points. The extra credit is only for work beyond what is expected in the project.