Types Of Network Games
When creating a networked game, there are two major paradigms -- client/sever versus peer-to-peer
Client-Server
In the client/server model, one machine works as a server that controls the gameplay, while other machines are clients, that only make change to the global state by making requests to the server. The server may be a "dedicated server" -- that is, a machine that no person is playing on, or one of the player's machines may act as a server. Massively Multiplayer Online games like World of Warcraft are all Client/server games, the Onlive service is a rather extreme version of a client-server model (where the clients are essentially sending keypresses down the wire, and getting video back)
Peer-to-Peer
In the Peer-to-peer model, there is no official server that all clients connect to -- instead each client does some calculation, and receives results from other machines. A two-person chat room (I send you messages, you send me messages) is a simple "pure" peer-to-peer network (once the connection has been made)
Combination Models
Most games that do not have a central server (which includes almost all xbox game) are a mix of client/server and peer-to-peer. One of the machines is specified as the server, and other machines connect to it. Some computation is done on each machine, but some central abritration is done by the server machine. Some care should be taken to ensure that the player playing on the server machine does not have an advantage over players on the client machines
Using XNA networking
XNA Networked games have the following flow (with some caveats below):

- While in the "wating for game to start" phase, you can send data back and forth from client to server. This could be used, for instance, to play a mini-game, or implement chat, while waiting for other players to join
- Don't even need to "officially" start the game, to move from the "lobby" to the "game". Once connected, you can start sending data and playing the game, without officially telling the networking layer that you have started
- Don't need to syncronize between client and server every frame. In fact, you probably don't want/need to update more often than about 10 times / second
Housekeeping details: Before you start
There are a few bits of code that you will need to include before you can start using the networking framework. First of all, you need to add a GamerServices component. Your constructor will need something like:
Components.Add(new GamerServicesComponent(this));
Also, before you can create a server (or search for one), a gamertag needs to be signed into the current machine (for both PC and xbox). Your update method should have something like the following at the beginning:
if (IsActive && Gamer.SignedInGamers.Count == 0) { // If there are no profiles signed in, we cannot proceed. // Show the Guide so the user can sign in. Guide.ShowSignIn(1, false); }
Note that you will definitely need to call the superclass update method in your update method (so that the GamerServices component will get update calls, which allows it to be functional
Creating a Network object
Creating a network object to host a game is easy, using the XNA networking library:
public static NetworkSession Create(NetworkSessionType sessionType, int maxLocalGamers, int maxGamers);
So, to create a network session for a simple game with one local player and one networked player, we could do something like:
networkSession = NetworkSession.Create(NetworkSessionType.SystemLink, 1, 2);
Once we have created a network session, we can hook up callbacks, so we can handle various network events:
- GamerJoined: When a gamer connects to us
- GameStarted: When we leave the lobby and start the game
- SessionEnded: When the Multiplayer session is over
All we need to do now is wait for our clients to connect, and signal that they are ready. Note that we also need to handle signalling when we are ready, and we will need to update the network session every frame so that it can do its work
Connecting clients
To connect to a host, we first find all available hosts, select one, and then connect to it.
AvailableNetworkSessionCollection availableSessions = NetworkSession.Find(NetworkSessionType.SystemLink, 1, null) // Connecting to first session we find: networkSession = NetworkSession.Join(availableSessions[0])
Of course, instead of connecting to the first one we find, we could instead take a look at various properties of each session, to find the one we want to join. When we join a game, we will also need to hook up network events, so that we can be notified of various network changes
Leaving the Lobby -- Starting the Game
Each player can say that she/he is ready by setting the IsReady property on the network session:
foreach (LocalNetworkGamer g in networkSession.LocalGamers) { g.IsReady = true; }
The host can check if everyone is ready, and start the game
if (networkSession.IsEveryoneReady && networkSession.IsHost) { networkSession.StartGame(); }
Once the game is started, then the GameStarted event is sent, the game is no longer considered availble, and the game can begin
Sending Data
To send data, first create a packet reader and packet writer, used to read an write packets. This can be done once, creating global (or local to your networking class) instance variables
PacketWriter packetWriter = new PacketWriter(); PacketReader packetReader = new PacketReader();
Once you have your packet writer, you can send data by first writing to the packet writer, and then sending the data off. For instance, if we were just sending a single Vector2, the position of our paddle for a networked pong game, we could do something like:
packetWriter.Write(mWorld.mMyPaddle.mObjectSprite.Position); networkSession.LocalGamers[0].SendData(packetWriter, SendDataOptions.InOrder);
To data, we can first see if there are any packets available, and then process it:
LocalNetworkGamer gamer = networkSession.LocalGamers[0]; while (gamer.IsDataAvailable) { NetworkGamer sender; // Read a single packet from the network. gamer.ReceiveData(packetReader, out sender); // Discard packets sent by local gamers if (sender.IsLocal) continue; // Read in any data // WARNING: be sure that your data sent matches the data received! Vector2 opponentPosition = packetReader.ReadVector2(); // Use the network data to update your current game state mWorld.mOpponentPaddle.mObjectSprite.Position = opponentPosition;
Example: Pong
Download the following .zip file, which contains necessary project files.
NetworkPong.zipNote that there are 3 solutions: A windows solution, an xbox solution, and a combo solution. Open both the windows and xbox solutions. Run both of them simultaneously to test your code. If you are making changes to a file, you only need to make changes in one solution (since the files are all shared). If you add a file to a project in a solution, you need to add it to the other solution as well (by using "add existing ...", or by adding the file using the combo solution).
Once you have everything running on the windows and 360 boxes, make the following changes:
- Add a ball and scoring, to make it an actual pong game
- Change the netorking so that it us updated 10 times a second instead of every frame.
- Update the code so that your paddle always appears on the left of the screen, and the opponent always appears on the right of the screen
- (Advanced) Modify the code to allow a 4-player (4 machine) networked game (each person gets one paddle. You can either have teams -- two paddles on each side of the screen -- or a 4-way pong playing field