A multithreaded game server
· Due 27 May by 23:00
· Points 15
This assignment requires you to design and implement a multithreaded game server suitable for two-player games (such as Backgammon, Checkers, Chess, Go, etc.). The server helps to pair up players and to coordinate the exchange of game moves. It does not know anything about the underlying game itself.
The server should be programmed using the C# programming language (Links to an external site.), and needs to be constructed using a synchronous server socket (Links to an external site.) from the ground up. Higher-level APIs (such as HTTPListener (Links to an external site.)) cannot be used. Please ask if in doubt.
The server should use HTTP REST as the basis for communication with the game clients. To this end, the following (GET) endpoints are suggested:
/register
This endpoint generates a random username for a player, registers this name, and returns to the user the registered name. The player is required to pass this username in all subsequent transactions for identification.
/pairme?player={username}
This endpoint attempts to pair the given player with another player. It returns a game record (or a suitable subset of it). The game record is a tuple containing a game ID, game state, username of the first player, user name of the second player, last move of the first player, and the last move of the second player.
When there is no other player waiting, the game record will contain a newly allocated game ID (which could be a GUID), a game state indicating "wait", and the username of the requesting player as first player. The rest of the elements in the tuple are not defined. When there is a waiting player, the game record will be the game record first created for the waiting player, updated to add the second player and the state indicating "progress". The state "progress" tells both players that the game can now begin.
The endpoint can be invoked by both players as many times as they want before the commencement of the game. This helps the first player to "poll" the state to see if a second player has been paired up.
/mymove?player={username}&id={gameId}&move={move}
This endpoint, when used during the game's "progress", will supply the user's move to the server. The "last move" of the player in the corresponding game record will be updated with this supplied move.
/theirmove?player={username}&id={gameId}
This endpoint, when used during the game's "progress", will collect the other player's move from the server. The game server will supply the "last move" of the other player from the game record corresponding to the given game ID.
/quit?player={username}&id={gameId}
This endpoint notes to the server the intention of the player to quit the game. The server will remove the game record corresponding to the given game ID. Attempt by the players to access the game record (for example, to get a move) will fail after the record is removed.
You may wish to implement other endpoints for diagnostic or informational purposes (e.g., a /debug endpoint or a /version endpoint). You may also wish to implement a /favicon.ico endpoint that supplies to the caller the "favicon" — this is particularly useful for browser-based clients.
You need to take appropriate actions when errors are encountered (e.g., invalid endpoints, malformed endpoints, invalid parameters to endpoints, etc.).
Typically, a single thread will handle a single player's endpoint interactions. The server, for the sake of efficiency, should keep the connection alive to handle the player's requests in the same thread. However, it is possible that the client may, from time to time, close the connection. For example, a browser will close the connection if it deems the connection inactive for a period of time. The server should be able to gracefully handle this scenario and continue to serve the client (potentially using a new thread).
Think about what information is shared among the threads and avoid potential race conditions efficiently using appropriate concurrency controls. You should not persist any of the information, meaning that, the information is kept only in nonpersistent memory and lost if the server is restarted.
The server should be a command-line application using .NET 6, and should be runnable with a standard .NET 6 installation (no third-party components are admissible). It should be able support browser-based game clients.
Testing
You need to come up with an appropriate testing strategy for verifying the correctness of the server. One way to do this could be to build a browser-based client for a chosen two-player game.
Report
Your submission should include a short report in the IEEE two-column style. The report should discuss the problem, explore alternatives, critically analyse your choices, design (which may include the specification), and implementation, and present an evaluation of your work. The report should include appropriate references. It should also have an appendix outlining what you learnt doing the assignment and any fedback or reflections you may want to share.