Сетевое программирование в .NET. Расшифровка IP-адреса (IP address specification). Обеспечение надежности доставки пакетов, страница 34

Background

The idea for Genesis was based on looking at the network protocols of the various online FPS games such as Quake and Half-Life, which use UDP to allow fast communication between the game server and its connected clients. These implementations have the option to send reliable and sequenced packets - abilities which are also incorporated into Genesis. The original intention for Genesis was to be the start of an underlying network API for a game engine written in .NET, however its potential is so great it has been given to the community as a standalone project.

Using the code

There are three interfaces that must be used to implement the Genesis functionality. These are:

¨  IConnection

¨  ICommand

IGenesisUDP

The IConnection objects hold information about each connection to a remote host, whether that host is a server or a client. ICommand holds information about a single command packet, including the opcode and data fields. IGenesisUDP is the actual communications class that controls all of the functionality.

Included with the source are two projects "GenesisChatServer" and "GenesisChatClient". These are a pair of projects that implement a chat system similar to IRC. Using these projects as a reference point should help with understanding the Genesis classes.

Creating A Server

Let's look at the GenesisChatServer - this project shows how Genesis can act as a server to serve other instances of Genesis (the clients). First, we need to declare and instantiate the Genesis object in the host application.

GenesisCore.IGenesisUDP m_UDP;

...

m_UDP = GenesisCore.InterfaceFactory.CreateGenesisUDP("ChatServer");

Notice how the class InterfaceFactory was used to create an instance of Genesis. The GetLocalAddresses method is used to return a list of local IP addresses on the current machine - and is used to populate a combo box in the chat server application.

string[] addresses = m_UDP.GetLocalAddresses( );

...

In order to handle the Genesis communication events, they must be hooked as per the code below:

//Hook genesis core events

m_UDP.OnListenStateChanged += new ListenHandler(m_UDP_OnListenStateChanged);

m_UDP.OnConnectionAuth += new ConnectionAuthHandler(m_UDP_OnConnectionAuth);

m_UDP.OnCommandReceived += new IncomingCommandHandler(m_UDP_OnCommandReceived);

m_UDP.OnConnectionStateChanged += new

ConnectionStateChangeHandler(m_UDP_OnConnectionStateChanged);

OnListenStateChanged is called when the state of the Genesis communication changes, it can be in one of two states: "Listen" or "Closed", which is just effectively like enabling or disabling the communication. When Closed, Genesis will drop all remote connections and close the socket.

OnConnectionAuth is called when a client has sent authorization information - this is where the client can be rejected if, for example, the logon credentials are not accepted. In the chat server example, the connection is rejected if the nickname is too short or if the server password is incorrect. Notice how a rejection reason can be sent back to the client. Everything is controlled by modifying the ConnectionAuthEventArgs object sent with the event. The command containing the authorization information can be accessed by the AuthCommand property of the event arguments.

void OnConnectionAuth(object o, ConnectionAuthEventArgs e)

{

...

if(e.AuthCommand.Fields[1].Length < 3)

{

e.AllowConnection = false;

e.DisallowReason = "Nickname too short.";

return;

}

else if(e.AuthCommand.Fields[1].Length > 15)

{

e.AllowConnection = false;

e.DisallowReason = "Nickname too long.";

return;

}

...

}