Game Creation with XNA/Networking/Network Engines
Network Engines
[edit | edit source]Other useful looking Engines:
- WCF - Windows Communication Foundation
- XNA integrated
- RakNet
Other interesting facts and examples can be found here: http://create.msdn.com/en-US/education/catalog/?devarea=19 , especially the one called Network Prediction.
Lidgren Network Engine
[edit | edit source]The Lidgren network engine is a .NET-based library made by Michael Lidgren. It can basically be used with every kind of .NET-Application. For delivery it uses a single udp socket and comes with classes for peer-to-peer and server-client connections. The engine runs under the MIT License, which makes it free to use. The current Version “gen3” requires .NET 3.5 or higher. Lidgren comes with an additional library that contains extension methods for some classes for a better XNA-Support. However you cannot use Lidgren for Xbox games.[1]
Important Classes
[edit | edit source]NetPeer
NetPeer represents the local connection point. It holds and creates connections to other peers. Important derived classes are NetServer and NetClient, which contain appropriate modifications for a server-client-system.
NetOutgoingMessage
An Object of this class is the carrier for your information. To create one, you have to use the CreateMessage()-method of your NetPeer object. With Write() you can put all your data into the message. Write() accepts all primitive types and objects.
NetIncomingMessage
This is used to hold the information about a received message. Additional to the content it says something about the MessageType, which can be library-related or data you have sent. *List of MessageTypes*
NetConnection
Represents the connection to a remote host.
Implementation
[edit | edit source]How to get started
- Download the latest version from the project's website.
- Open the "Lidgren XNA Extensions/Lidgren XNA Extensions.sln"-file and compile the solution.
- Copy the created .dll-files in your project folder and reference to them within your project.
- Now you should be able to use the Lidgren.Network namespace.
How to create a Peer
class Program
{
//hold the NetPeer Object as a member
//In this example I use a server, because it is more common to work with server and clients
private NetServer server;
public Program()
{
//When initialising, create a configuration object.
NetPeerConfiguration config = new NetPeerConfiguration("Server");
//Setting the port, where the NetPeer shall listen.
//This is optional, but for a server its good to know, where it is reachable
config.Port = 50001;
//Create the NetPeer object with the configurations.
server = new NetServer(config);
//Start
server.Start();
}
}
How to send a message
//get a message from the servers message pool
NetOutgoingMessage msgOut = server.CreateMessage();
//write your data
msgOut.Write("Some Text");
msgOut.Write((short)54);
//send the message to a client
server.SendMessage(msgOut, client, NetDeliveryMethod.ReliableOrdered);
The different NetDeliveryMethods are explained here
How to receive a message
//use local message variable
NetIncomingMessage msgIn;
//standard receive loop - loops through all received messages, until none is left
while ((msgIn = server.ReadMessage()) != null)
{
//create message type handling with a switch
switch (msgIn.MessageType)
{
case NetIncomingMessageType.Data:
//This type handles all data that have been send by you.
break;
//All other types are for library related events (some examples)
case NetIncomingMessageType.DiscoveryRequest:
//...
break;
case NetIncomingMessageType.ConnectionApproval:
//...
break;
}
//Recycle the message to create less garbage
server.Recycle(msgIn);
}
A description for all MessageTypes can be found here
How to connect to a server
[2]
The first step is to enable three specific message types.
//for the server
serverConfig.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
serverConfig.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
//for the client
clientConfig.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);
After initialising the client you can search for the server. Therefore, you can send a request to an ip address or search all systems in your local network.
//search in local network at port 50001
client.DiscoverLocalPeers(50001);
The server has now received a DiscoveryRequest which has to be handled by the "receive message loop"
case NetIncomingMessageType.DiscoveryRequest:
NetOutgoingMessage msg = server.CreateMessage();
//add a string as welcome text
msg.Write("Hellooooo Client");
//send a response
server.SendDiscoveryResponse(msg, msgIn.SenderEndpoint);
break;
The Client has now received a DiscoveryRequest by the server. Assuming there is just one server in your local network you can simply connect to it.
case NetIncomingMessageType.DiscoveryResponse:
Console.WriteLine("Server answered with: {0}", msgIn.ReadString());
client.Connect(msgIn.SenderEndpoint);
break;
The last step is to receive the ConnectionApproval message at the server and to approve the connection.
case NetIncomingMessageType.ConnectionApproval:
msgIn.SenderConnection.Approve();
break;
Raknet
[edit | edit source]RakNet is a library with several classes to perform networking solutions and developed by Jenkins Software LL. It is a cross-platform for C++ and C#. Therefore, it can be used on all major platforms, including Android and iOS. Main features are object replication, lobby system, secure connections, voice communication and an autopatcher.[3]
Swig
[edit | edit source]Swig can be used to generate wrapper code for a native DLL allowing to use RakNet in C#.[4] Swing generates CXX and .h files that represent the interfaces as well as inclusions for the C# project to connect to the DLL. How to use Swig see the detailed description.
Important Classes
[edit | edit source]RakPeerInterface
[edit | edit source]Even though RakPeerInterface is not an actual class it is the main interface for the network communications and the responsible for the startup. An instance of a peer is return by calling the .GetInstance() method.[5]
SocketDescriptor
[edit | edit source]An instance describes the local socket which can be used for the startup.[5] It is possible to define the port with parameters or use 0 to automatically pic a free port. In addition if desired an array of socket descriptors can be made.[6]
Packet
[edit | edit source]It represents a message from another system/computer and contains information about the message, such as length, bit size or id of sender.
Implementation
[edit | edit source]=====Connection as Client===== [7]
using UnityEngine;
using System;
using System.Collections;
using RakNet;
public class ConnectClient {
public static string remoteIP = “127.0.0.1″;
RakPeerInterface myClient;
SocketDescriptor scktDist;
//…
void Awake() {
myClient = RakPeerInterface.GetInstance();
scktDist = new SocketDescriptor();
// Prameters: 1) max. number of connection 2) SocketDescriptor to specifie ports/addresses
myClient.Startup(1,scktDist,1);
}
void OnGUI(){
//…
// if not yet connected
myClient.Connect(remoteIP, 25000, “”,0);
//…
}
}
===== Connection as Server=====[8] Starting a server is very similar to the instructions above.
public class ConnectServer {
public static string remoteIP = “127.0.0.1″;
public static int maxConnectionsAllowed = 4:
public static int maxPlayersPerServer = 10;
RakPeerInterface server;
SocketDescriptor scktDist;
//…
void Awake() {
server = RakPeerInterface.GetInstance();
scktDist = new SocketDescriptor();
server.Startup(maxConnectionsAllowed, 30, scktDist, 1);
server.SetMaximumIncomingConnections(maxPlayersPerServer);
}
}
===== Reading of Packets=====[8] Remarks, Ii a packet is 0 nothing is to read.
public class PackageReading {
RakPeerInterface server;
Packet p;
//…
void Reading() {
while (true) {
if (p = server.Receive()) {
// do something terribly interesting with p...
}
}
}
}
===== Sending of Packets=====[9] Remarks, it is used BitStreams to create the "packets".
public class PackageReading {
RakPeerInterface peer;
Packet p;
//…
void Sending() {
MessageID useTimeStamp; // Assign this to ID_TIMESTAMP
Time timeStamp; // Put the system time in here returned by GetTime()
MessageID typeId; // This will be assigned to a type I've added after ID_USER_PACKET_ENUM, lets say ID_SET_TIMED_MINE
useTimeStamp = ID_TIMESTAMP;
timeStamp = GetTime();
typeId=ID_SET_TIMED_MINE;
BitStream message = new BitStream();
message.Write(useTimeStamp);
message.Write(timeStamp);
message.Write(typeId);
message.Write("Hallo",5);
peer = Send(BitStream * bitStream,HIGH_PRIORITY,RELIABLE,0,UNASSIGNED_SYSTEM_ADDRESS,true);
}
}
Links
[edit | edit source]Windows Communication Foundation
[edit | edit source]The Windows Communication Foundation (WCF) from Microsoft is a platform or application programming interface that bundles several technologies for building connected services or programs. Microsoft defines its features: orientation, interoperability, multiple message patters, service metadata, security and AJAZ and REST support.[10] It supports SOAP over HTTP, TCP, Message Queues, etc. WCF requires Windows XP SP2 or higher.[11]
References
[edit | edit source]- ↑ http://code.google.com/p/lidgren-network-gen3/ - project page at google code
- ↑ http://www.xnamag.de/article.php?aid=19#chapter3 - article about connections between server and clients
- ↑ http://www.jenkinssoftware.com/
- ↑ http://www.jenkinssoftware.com/raknet/manual/swigtutorial.html
- ↑ a b http://www.jenkinssoftware.com/raknet/manual/Doxygen/
- ↑ http://www.jenkinssoftware.com/raknet/manual/startup.html
- ↑ http://txcom2003.wordpress.com/2011/05/29/unity-3d-and-raknet-4/
- ↑ a b http://www.jenkinssoftware.com/raknet/manual/detailedimplementation.html
- ↑ http://www.jenkinssoftware.com/raknet/manual/creatingpackets.html
- ↑ http://msdn.microsoft.com/en-en/library/ms731082.aspx
- ↑ http://msdn.microsoft.com/de-de/library/ms733890.aspx
Authors
[edit | edit source]mglaeser and juliusse