The network library in ClanLib sports a simple event based networking engine usually referred to as the NetGame engine. In all its simplicity the engine assist in routing simple messages from a client to a server and back.
The API consists of the following classes:
On the server side, the game must construct an instance of clan::NetGameServer. Then for each port that the server should listen on, it must call clan::NetGameServer::start(port).
The class also features three important signals:
clan::NetGameServer is a clan::KeepAlive based class, which means that during calls to clan::KeepAlive::process() the class will emit those three signals for each client that has connected/disconnected since last call, and for each game event that arrived since last.
It is also possible to call process_events() on the clan::NetGameServer or clan::NetGameClient objects directly to cause the signals to be emitted. Generally, in client applications the signals are processed automatically because the main render loop already calls the clan::KeepAlive::process() function, but for servers that to not use clanDisplay the process_events() function can be called directly.
The clan::NetGameClient class is similar in design, except that there is only one connection (to the server), and therefore the connect/disconnect signals do not include any clan::NetGameConnection objects.
The class clan::NetGameEvent represents a game event message that is either sent or received. Each event consists of two things: an event name and list of event parameters. The name is what identifies what the event is about, while each of the parameters can one of the following types:
Lets say that the client wants to send a log on message to the server. We want to pass a username and a password as the arguments, so we do like this:
The constructor for clan::NetGameEvent exist in 6 versions, allowing you to pass anything from 0 to 5 parameters in a single line. The types of the parameters are automatically deducted from the C++ type you pass for each parameter. If you need to pass more parameters than this, then you need to use the add_argument(const clan::NetGameEventValue &value) function on clan::NetGameEvent.
On the server, this game event will be emitted via the sig_event_received, and might be handled like this:
An example of a NetGame based server can be found in the ClanLib examples.
To illustrate how a game can be built using this system, the following listing shows what events are used in the DiceWar example while the game itself is running:
When a clan::NetGameEvent is received, we can attach a callback function to the event, or event group, that will handle the event. That's where the clan::NetGameEventDispatcher classes are handy. There are 4 constructors for the clan::NetGameEventDispatcher class, in order to dispatch from 0 to 3 extra arguments.
Let's say that on the server side, we want to dissociate account operations events (sent by the client to register a new account), from the login events.
Here we want to be able to handle 3 types of events:
We will then set each functions to handle each events:
Here we want to handle 2 types of events:
The difference here is that we will want to be able to pass the clan::NetGameConnection attached to the client on the server, to the dispatcher as an extra argument. That is why we will use clan::NetGameEventDispatcher_v1< ContextParam > class.
Same as before, we set the handlers:
Now that we've set our event handlers, we need to tell the system where to dispatch the events. This will be done for example in the on_event_received() method.
The dispatcher will invoke the callback function that we set, or print that the event hasn't been handled.