C代写:CS449 Multi User RPG

代写网络RPG游戏,练习Linux网络编程。

Description

In this project we are going to convert the single-user RPG game we wrote for Project 4 into a multi-user RPG game. In order to support multiple users in a single RPG world, you need a server that maintains that world to which multiple clients can connect to. Hence, you will have to do network programming using Berkeley sockets. Also, in order to support multiple simultaneous users, you cannot have a TCP server that processes each client connection sequentially. Hence, you will have to write a multithreaded server where each client connection is serviced through a different thread. For this, you will use POSIX threads (pthreads). We will learn about pthreads during the lectures.

Functionally, it is going to be mostly the same as the RPG game we made for Project 4, other than the multi-user part except for one thing: you do not need to support signals and related functionality for Project 5. Also, we are going to modify one thing internally: we will no longer use the /dev/dice device file to generate random rolls. You will replace it with the version you had for Project 1 using rand().

Dividing your RPG into a server program and a client program is going to require some thinking. What components should go into each side? For one, the server should maintain all the state for your game since that state must be visible across all clients. That means all modifications to that state will also be done by the server. Then what does the client do? It does two things mostly: 1) Reads state from the server across the network and displays it to the player and 2) Requests modifications to the state by sending ‘commands’ to the server. It is the same relationship your SSH terminal has with the thoth server: every action is performed in actuality by the server and your terminal is used to just display the result of those actions or send commands.

Communicating between the server and the client will also require you to design an application level protocol. A protocol is set of rules on who sends what at what point and also the layout of the messages that go back and forth. You are free to design your own protocols, although I will give you some suggestions in the later sections of this worksheet. The protocol must be binary-based and not textbased (like you did for the lab). This is the natural choice because you will be transferring mostly structs (structs representing character info, structs representing rounds of a fight, ) across the network. It will actually be more work for you to convert these structs to text format and back.

Ports and Addresses

We will use the same ports assigned to you that you used for the network programming lab to run your server. Please use these ports and these ports only.

For an address of the machine, we will simply use 127.0.0.1 (the localhost).

Requirements

Your task is to write two programs: rpg_server and rpg_client. The rpg_server will bind to your designated port, listen on it, and accept connections just like we did for the lab. Once it accepts a connection, it is going to create a new thread passing the new socket file descriptor as an argument to the thread start function. Henceforth, all communication with the client will occur within that thread using that socket. When the client quits, the thread should terminate. All the threads will operate on a shared state (namely, the list of NPCs and their respective states and the list of players and their respective states). Whenever multiple threads access a shared state and at least one thread modifies that state you need to perform synchronization to avoid data races. You will use pthread_mutex_lock and pthread_mutex_unlock that we will learn in class for this purpose. The rpg_server will take one command line argument: the port number to listen to:

thoth $ ./rpg_server 10000

The rpg_client can remain single threaded. It will connect to the server and communicate with it to request various actions and display the results. The rpg_client will take one command line argument: the port number to connect to:

thoth $ ./rpg_client 10000

Along with the two programs, you are required to submit a Makefile to build these programs. See below section on Makefile for specific requirements.

Multi-User RPG Changes

This section describes functional changes you will have to make to your existing Project 4 single-user RPG to make it multi-user. The changes are described using an example where two players login to the server simultaneously. We have three SSH terminals: one for the server and one for each player.

Server Terminal

thoth $ ./rpg_server 10000

The server does not print any output unless there is an error condition. It silently waits for and processes client connections.

Player 1 Terminal

thoth $ ./rpg_client 10000
What is your name?
Frodo

User profile not found. Creating new character...

List of available armors:
0: cloth (AC=10)
1: studded leather (AC=12)
2: ring mail (AC=14)
3: chain mail (AC=16)
4: plate (AC=18)

Choose Frodo's Armor (0~4): 3

List of available weapons:
0: dagger (damage=1d4)
1: short sword (damage=1d6)
2: long sword (damage=1d8)
3: great sword (damage=2d6)
4: great axe (damage=1d12)

Choose Frodo's Weapon(0~4): 1

Player setting complete:
[Frodo: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000]
command >> look
All is peaceful in the land of Mordor.
Sauron and his minions are blissfully going about their business:
0: [Sauron: hp=115, armor=plate, weapon=great axe, level=20, xp=1048576000]
1: [Orc 1: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000]
2: [Orc 2: hp=20, armor=cloth, weapon=great sword, level=1, xp=2000]
3: [Orc 3: hp=20, armor=studded leather, weapon=long sword, level=1, xp=2000]
4: [Orc 4: hp=20, armor=studded leather, weapon=long sword, level=1, xp=2000]
5: [Orc 5: hp=20, armor=cloth, weapon=great axe, level=1, xp=2000]
6: [Orc 6: hp=20, armor=studded leather, weapon=dagger, level=1, xp=2000]
7: [Orc 7: hp=20, armor=ring mail, weapon=short sword, level=1, xp=2000]
8: [Orc 8: hp=20, armor=chain mail, weapon=long sword, level=1, xp=2000]
9: [Gollum: hp=10, armor=cloth, weapon=dagger, level=1, xp=2000]
Also at the scene are some adventurers looking for trouble:
0: [Frodo: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000] 
command >>

The server looks for the name Frodo in its list of existing characters and responds back to the client with a not found message. The client subsequently collects info from the player and registered the new character with the server. Other than that, it looks very much like the single-user RPG so far.

Player 2 Terminal thoth

$ ./rpg_client 10000
What is your name?
Sam

User profile not found. Creating new character...

List of available armors:
0: cloth (AC=10)
1: studded leather (AC=12)
2: ring mail (AC=14)
3: chain mail (AC=16)
4: plate (AC=18)

Choose Sam's Armor (0~4): 0

List of available weapons:
0: dagger (damage=1d4)
1: short sword (damage=1d6)
2: long sword (damage=1d8)
3: great sword (damage=2d6)
4: great axe (damage=1d12)

Choose Sam's Weapon(0~4): 1

Player setting complete:
[Sam: hp=20, armor=cloth, weapon=short sword, level=1, xp=2000]
command >> look
All is peaceful in the land of Mordor.
Sauron and his minions are blissfully going about their business:
0: [Sauron: hp=115, armor=plate, weapon=great axe, level=20, xp=1048576000]
1: [Orc 1: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000]
2: [Orc 2: hp=20, armor=cloth, weapon=great sword, level=1, xp=2000]
3: [Orc 3: hp=20, armor=studded leather, weapon=long sword, level=1, xp=2000]
4: [Orc 4: hp=20, armor=studded leather, weapon=long sword, level=1, xp=2000]
5: [Orc 5: hp=20, armor=cloth, weapon=great axe, level=1, xp=2000]
6: [Orc 6: hp=20, armor=studded leather, weapon=dagger, level=1, xp=2000]
7: [Orc 7: hp=20, armor=ring mail, weapon=short sword, level=1, xp=2000]
8: [Orc 8: hp=20, armor=chain mail, weapon=long sword, level=1, xp=2000]
9: [Gollum: hp=10, armor=cloth, weapon=dagger, level=1, xp=2000]
Also at the scene are some adventurers looking for trouble:
0: [Frodo: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000]
1: [Sam: hp=20, armor=cloth, weapon=short sword, level=1, xp=2000]
command >>

The client registers the new character Sam as before. Note that the list of NPCs is exactly the same as the one for Player 1. Also, note that Player 2 sees an existing player character that registered before her named Frodo (vice versa, if Player 1 had looked at this point, she would also see Sam in the list).

Player 1 Terminal

command >> quit
thoth $ ./rpg_client 10000
What is your name?
Frodo

Existing user profile found. Loading ...

[Frodo: hp=20, armor=chain mail, weapon=short sword, level=1, xp=2000]
command >>

Now Player 1 one quits and then logs back in with the same name Frodo again. The server finds the name in its player list and responds back to the client with the relevant user information.

Network Protocol

You will design your own network protocol using binary data packets. You will mostly be transferring numbers and structs. This section lays out some general suggestions on how to design your protocol but you are not obliged to follow it.

Network Message Design

Most application protocols send a fixed-size header before sending the actual data payload. The header contains information on what type of message this is, as well as additional information about the payload. The header structure is designed to be the same regardless of the payload. That way the receiver side can first look at the header and know how to deal with the incoming payload. Sometimes the payload will be variable length (e.g. list of players, list of fight rounds). In that case, the header should contain information about the length of the payload. Subsequent sections will describe the type of messages that would go back and forth for each player scenario.

Makefile

You are required to write a Makefile to build your multi-file project. The Makefile and your project should satisfy the following requirements:

  • Your project at minimum must have 3 source files: rpg_client.c, rpg_server.c, and common.h
  • Header common.h must be #included in both your .c files and contains common declarations, struct type definitions, and #defines. It should not define any functions or variables.
  • On ‘make’ your Makefile must build both the rpg_client and rpg_server binaries.
  • On second ‘make’ with no modification, your Makefile should not perform any actions.
  • On modification of rpg_client.c, your Makefile should only build rpg_client.
  • On modification of rpg_server.c, your Makefile should only build rpg_server.
  • On modification of common.h, your Makefile should build both rpg_client and rpg_server.

Hints and Notes

  • There is a reference implementation for the RPG game at: ~wahn/public/cs449/rpg_server and ~wahn/public/cs449/rpg_client. To observe behavior described in the worksheet, please try running the above binary.

  • Players can only fight NPCs not each other. They do it through the same command as before: fight <NPC number>.

  • When accessing any server data structure shared by multiple threads, pthread mutex locking must be performed so other threads can never view inconsistent state.

  • You are free to limit the number of registered player characters to 10. Your server will not be tested beyond that limit.

  • You are free to design your own protocol. The diagrams are just a suggestion.

Submission

You need to submit:

  • Source files for both rpg_server and rpg_client
  • Your Makefile
  • Do not submit any binaries or object files. Your Makefile must be able to build from scratch on the initial invocation of ‘make’.

Make a tar.gz file as in the first assignment, named USERNAME-project5.tar.gz

Copy it to ~wahn/submit/449/RECITATION_CLASS_NUMBER by the deadline for credit.