category-group: servers
layer(s): 10

header file(s): z_server.h

synopsis.
The server group contains primarily only one object: the class server_o (there is also the execmon_actor_o class, which is a little raw at the moment and we don't recommend using it currently).

A server object is by no means 'small'. Servers utilize the complete set of classes created in the transport group. The server class provides a framework for creating a server in the traditional computer sense: a long-running, standalone program that waits for other programs ("clients") to connect to it, sending their requests. The server object then goes and does something, usually sending an answer back to the connected client.

Vettrasoft has strived to make this object as universal and general-purpose as possible. However, as with any complex software system, there are some protocols and assumptions that form the behaviour of this object. Some of these are:

  • sockets are the means for server communication. although the transport system is architecturally designed to support multiple message transport systems, sockets is the only one currently implemented.
  • a server's "port" can be designated to recieve input only, to send output only, or be bi-directional. This may come as a surprise to some, but in the case where you have a set of servers that pass messages in a predefined manner (say, a fixed data flow), this allows for chaining servers that process data, sending the output from server A as the input to server B, which then gets forwarded to server C, etc. . If you wish the traditional single input-output port, that is of course easily done, too.
  • a single server object can have multiple input and output ports.
  • servers are oriented to work with data-bags. Since data-bags are an integral part of the Z Directory, and an excellent protocol for data, the server object is specifically handled to process them. There are 2 call-back functions provided for incoming messages:
    process_message()
    process_dbag()
  • a server can run forever (until killed).
    a server can have a specific lifetime.
    you can specify the maximum amount of time (dynamically!) that a server can wait for input.
    you can do "background work" [via member funcion periodic_work()] between waiting for input.

For a complete specification of the server object, please go to its page.

classes in this group: server_o, execmon_actor_o

support/internal classes: server_dbag_o

description.
The Z Directory server class have the following characteristics:
- they are event-driven
- an event can be a timer, or a message recieved on an input channel.
- there can be an unlimited number of input channels. However, all messages are funneled to the same function (demultiplexed?). The function recieves a parameter in its argument list that provides information about the message, such as from which channel it came from.
- servers can belong to a group. The group can be controlled by an "executive monitor" - a specialized type of server that manages other servers.

usage.
You can make and run a server in 3 lines of code: header file, instantiation, and "go do it":

#include "z_server.h"
// ..
server_o x;
x.run();

However, the server above will do nothing useful. For that, you need to make your own member function "process_message(). The right way to use the server_o class is to subclass from it:

#include "z_server.h"
class My_Server : public server_o { /* .. */ };

// .. int ie; My_Server x; msgtrans_sockaddr_o sa; msgtrans_sockaddr_o my_port1, my_port2; sa.set_port (5000); my_port1 = x.add_channel (sa, &ie); // add a non-dbag I/O port sa.set_port (7000); my_port2 = x.add_channel (sa, &ie); // add another (port 7000)
timespan_o ts ("13 seconds"); // need to use timespan object x.set_max_sleep (ts); // make a 13-second delay ts = "100 days"); // recycle timespan object x.set_max_life (ts); x.dont_daemonize(); // this is a no-op on Windows
x.run();

In this example, the server ("My_Server", instance 'x') has 2 [non-databag] ports, at port numbers 5000 and 7000. With the "run()" call, it is up and running. Notice that it will loop every 13 seconds, checking any input (and output) ports for pending data or connections. New connections are automatically procesed. When it recieves a connection or message, however, it won't do anything with it, as no 'callback' functions have been defined. To make it work do this:

int My_Server::process_message (const msgtrans_addr_o &mta, string_o &s)
{
    std::cout << "INPUT MESSAGE ---> \"" << s << "\"\n";
    string_o s2 ("/CONFIRMED");
    send_message (mta, s + s2);
    return 0;
}
In this case, the server will simply tack on the string "/CONFIRMED" to the input, and echo it back to the client.

note.
Some may call these things agents or actors. This object employs the traditional, popular name "server".

warnings.
The documentation for the server class is very large.