Privacy and Security Notice

CDEV Generic Server



The CDEV Generic Server

A CDEV Extension Library for Building Client/Server Systems

Version 1.5 December 9, 1996

Walt Akers, Chip Watson, Jie Chen

TJNAF - Thomas Jefferson National Accelerator Facility




Table of Contents

1.
Overview of the CDEV Generic Server Engine

Purpose of This Document

Intended Audience

What is the CDEV Generic Server Engine

Why Use the CDEV Generic Server Engine

Features
2.
Building the CDEV Generic Server Engine

Steps for Compiling and Testing the CDEV Generic Server Engine
3.
The Reflector Server - A Simple Client/Server System

Overview

Reflector Server Source Code

ReflectorServer Header Files

The ReflectorServer Class

The main Function

The ReflectorService Source Code

The ReflectorService.h Header File

The newReflectorService Function

The ReflectorService Class

The CDEV DDL File

Testing the Reflector Server
4.
Server Class Hierarchy

Server Classes

FifoQueue Class

MultiQueue Class

ClientSession Class

Attributes of the ClientSession Class

localID

clientID

socketID

SocketSession Class

Attributes of the SocketSession Class

socketID

ClientAcceptor Class

SocketReader Class

SocketWriter Class

ClientHandler Class

cdevSessionManager Class

cdevServer Class
5.
Client Class Hierarchy

Client Classes

SocketReader Class

SocketWriter Class

ServerHandler Class

ServerHandlerCallback Class

ServerConnectionList Class

cdevServerInterface Class

cdevClientRequestObject Class

cdevClientService Class
6.
Properties of the cdevSessionManager Class

Overview

Attributes of the cdevSessionManager Class

Reactor

trigger

rate

localIdx

inbound

clients

sockets

Methods of the cdevSessionManager Class

getNextLocalID

newClientSession

newClientSession

findLocalClient

findClient

findSocket

addClient

addSocket

removeClient

removeSocket

enqueue

enqueue

dequeue

decodePacket

encodePacket

get_handle

handle_input

handle_close

handle_timeout

set_rate

get_rate

processMessages
7.
Properties of the cdevServer Class

Overview

Attributes of the cdevServer Class

Finished

serverName

acceptor

timer

status

Methods of the cdevServer Class

cdevServer

newClientSession

newSocketSession

dequeue

decodePacket

encodePacket

operational
8.
Properties of the cdevServerInterface Class

Overview

Attributes of the cdevServer Interface Class

Reactor

connections

domain

defaultServer

defaultServerHandler

maxFd

fdList

Methods of the cdevServer Interface Class

cdevServerInterface

getDefault

getDomain

setDefault

connect

disconnect

enqueue

getFd

flush

pend
9.
Properties of the cdevClientService Class

Overview

Attributes of the cdevClientService Class

callback

transactions

contexts

tagCallback

Methods of the cdevClientService Class

cdevClientService

defaultCallback

outputError

flush

pend

poll

pend

getNameServer

getRequestObject

enqueue

cancel

enqueue

fireCallback
10.
Properties of the cdevClientRequestObject Class

Overview

Attributes of the cdevClient RequestObject Class

sendStatus

server

DDL_server

syncCallback

handler

contextID

commandCode

messageCode

Methods of the cdevClient RequestObject Class

constructor

setContext

send

sendNoBlock

sendCallback

className

defaultCallback

executeServer HandlerCallback

getServerHandler

getContextID

getCommandCode

getMessageCode
11.
Implementing Monitoring on the cdevServer

Overview

Special Notes

Attributes of the cdevMonitorTable Class

monitors

Methods of the cdevMonitorTable Class

insertMonitor

removeMonitor

remove ClientMonitors

findMonitor

fireMonitor

fireCallback

Attributes of the cdevMonitorNodeClass

parent

node

hashString

Methods of the cdevMonitorNode Class

fireMonitor

isMonitored
12.
VirtualService: A Complex Client/Server Implementation

Overview

Virtual Server Structure

Virtual Service Structure

VirtualAttrib.h

VirtualAttrib.cc

VirtualServer.h

VirtualServer.cc

VirtualService.h

VirtualService.cc

Virtual.ddl



List of Figures

Figure 10: ReflectorServer.cc - Source Code for the Reflector Server
Figure 11: ReflectorService.h - Header File for the Reflector Service
Figure 12: ReflectorService.cc - Source Code for the Reflector Service
Figure 13: Reflector.ddl - A Simple CDEV DDL File
Figure 1: Object Hierarchy of Server Classes
Figure 2: Object Hierarchy of Client Classes
Figure 3: General Structure of the cdevMonitorTable
Figure 4: Components of the Virtual Server
Figure 5: Components of the Virtual Service



1.

Overview of the CDEV Generic Server Engine

Purpose of This Document

This document is designed to provide an overview and tutorial of how to implement client/server applications by using the CDEV Generic Server Engine. Adherence to the structure and syntax that is specified in this document will improve the likelihood that the CDEV service/server developer's application will be compatible with other similar applications using CDEV.

The class library was designed to be as efficient as possible and still maintain the flexibility to allow CDEV client/server developers to use it with minimal modification. In addition to describing the conceptual behavior of the server, this document will also discuss the C++ classes and how inheritance and overloading may be used to build the best server for your application.

Intended Audience

This document is intended for anyone who will be developing a CDEV server or will be developing CDEV applications that will communicate with one another over a network. This document will also be useful for software developers who wish to develop a non- CDEV application that can communicate with an existing server that uses this class library.

What is the CDEV Generic Server Engine

The CDEV Generic Server Engine is a collection of C++ classes that may be used to quickly develop a client/server application. The communications component of the library is based on the Adaptive Communications Environment (ACE), a freeware product developed by Douglas Schmidt that is provided with the CDEV distribution.

CDEV servers use a global CDEV Name Server (provided with the source code distribution) to register themselves. The client services can then use this Name Server to locate servers by type, name or host. The Name Server insures that each server name is unique within its type or domain. Servers that have not reregistered within a specific time period (usually 60 seconds) are automatically removed from the Name Server.

Clients and servers that are developed using this library will use the CDEV Linear Internet Protocol to communicate. The documentation for this protocol is provided with the CDEV distribution and its use ensures that the developer's server will be accessible by all CDEV compliant applications.

Why Use the CDEV Generic Server Engine

The CDEV Generic Server Engine provides a robust and reliable mechanism for quickly developing client/server applications. Because all of the network communications intricacies are isolated by the C++ classes, the developer's server can easily be modified and upgraded without significant modification to the network internals. Additionally, by using CDEV, the client does not need to be 'network-aware', the client C++ class library does all of the communications work.

The CDEV Generic Server Engine also provides a myriad of features that would require a significant investment in time to develop for each new server. These features are described in detail below.

Features

The developer is only required to create a subclass of the cdevServer C++ class and overload a single method in order to generate the communications component of his server.

The complete client communications portion of the application is accomplished by inheriting a CDEV service class from the cdevClientService C++ class and writing a boiler plate service loader.

The engine uses the CDEV Linear Internet Protocol (CLIP) to communicate. This protocol uses cdevData objects (a self-describing data structure) to transfer data allowing unique, application specific data structures to be transferred without modifying the protocol.

The client and server side of the application use a global CDEV Name Server to register and locate various servers by their type, name or host.

The socket utility classes use embedded buffering to optimize asynchronous communications and increase communications speed.

The communications interface is completely abstracted from the client application. Because the application has only a CDEV view of the world, the underlying communications engine can be modified or upgraded without breaking the program.

Clients automatically reconnect to server following a disconnect or communications error.

Communications integrity is ensured by using TCP/IP and the Adaptive Communications Environment (ACE) C++ library.

The server supports multiple concurrent client connections. Because the inbound data is read incrementally and buffered, a slow client will not cause the server to block while waiting for a transmission to be completed.

The server is completely event driven. It is activated whenever a client submits a packet or packets, otherwise, it sleeps until it has inbound data to process.

An individual tag map is maintained for each connection. When data is received the server will map the contents of the clients cdevData objects to the server's representation prior to processing. The cdevData objects are remapped to the client's representation prior to returning results.

The server has built-in mechanisms for storing, executing and removing client specified monitors on server data objects. This monitoring capability easily allows application developers to create event-driven client programs that respond to changes in the server.

A timer-based CDEV 'polling' class is provided that allows the server to attach to other CDEV servers or services to obtain information.

2.

Building the CDEV Generic Server Engine

Steps for Compiling and Testing the CDEV Generic Server Engine

1.

Install and compile the CDEV source code distribution. See the CDEV distribution for specific instructions for compiling these libraries.

2.

Compile the Adaptive Communications Environment (ACE) Library. ACE is located at the same level as the 'src' directory in the CDEV distribution tree. The README file located in that directory will provide specific instructions on building this library on your system. The ACE libraries should be automatically copied to the CDEV library directory.

3.

Setup the Makefile for your platform. In the directory include/makeinclude there are a collection of makefiles that are followed by the name of the platform for which they were developed. Link the makefile associated with your platform to the file Makefile.OS by typing the following command: "ln -s Makefile.XXXX Makefile.OS".

If a makefile for your platform does not already exist, you may have to create one in that directory.

4.

Compile the cdevGenericServer Library. The source code tree for this distribution is located in the directory $CDEV/extensions/cdevGenericServer.

The makefile for this library requires the same environment variables that are used by the main CDEV makefile.

CDEV

This is the root directory of the CDEV distribution.

CDEVVERSION

This is the version number of the CDEV class library.

CDEVSHOBJ

This is the directory for the CDEV shared objects.

CDEVLIB

This is the directory where the CDEV libraries reside.

CDEVINCLUDE

This is the directory where the CDEV include files reside.

To compile the libraries, go to the cdevGenericServer directory and type make. All libraries and the associated test and example applications should be built.

5.

Run the test applications to ensure that the code is working correctly. These applications are located in the test sub-directory of the cdevGenericServer tree. The test applications require that a special DDL file is specified and that the CDEV Name Server is operating. Perform the following steps to test the library.

5a.

Start the Name Server. The NameServer application is located in the bin directory of the cdevGenericServer distribution tree. The NameServer should produce no output and can be executed in the background by typing: "NameServer &".

5b.

Specify the host name of the Name Server. Because all applications will need to access the Name Server, the host where it is executing should be specified in the CDEV_NAME_SERVER environment variable. This variable must be specified in the environment of each shell that will need to access the Name Server. If the Name Server is running on host foo.cebaf.gov, the Name Server environment variable can be set by typing: "setenv CDEV_NAME_SERVER foo.cebaf.gov".

5c.

Specify the CDEV Device Definition Language file for the test programs. The DDL file for the test programs is named TestService.ddl and is located in the test sub-directory of the cdevGenericServer distribution tree. In order for this DDL file to be used as the default, it should be specified in the CDEVDDL environment variable. This can be accomplished by moving to the test directory and typing the following command: "setenv CDEVDDL $PWD/ TestService.ddl".

5d.

Specify the CDEVSHOBJ directory. The CDEVSHOBJ directory is the directory that contains the versioned subdirectories for the service shared objects. By default the makefile will place the file TestService.so in the directory $CDEV/lib/PLATFORM-OSVERSION.XX/1.5/TestService.so, where PLATFORM is the name of your platform and OSVERSION is the major operating system. The following example shows the location of the TestService.so on a Solaris 5.5 system and the correct setting for the CDEVSHOBJ variable.

Location: $CDEV/lib/solaris-5.XX/1.5/TestService.so

CDEVSHOBJ: $CDEV/lib/solaris-5.XX

The CDEVSHOBJ variable may point to the directory that actually contains the service shared objects, however, CDEV will always attempt to locate the files in the version subdirectory first in order to support multiple CDEV versions.

5e.

Start the Test Server. The environment is now correct to start the TestServer. From the bin sub-directory type the command: "TestServer". The TestServer should print a message indicating that it is ready to process user requests.

5f.

Specify the Client Tag Map. In order to test all capabilities of the server, the client should use a tag map that is different from the one that is in use on the server side of the connection. A special tag map has been provided that can be used to test this feature. The tag map is located in the test sub-directory and can be specified by moving to the test subdirectory and typing: "setenv CDEVTAGMAP $PWD/cdevTagMap.txt".

5g.

Start the Test Client. In a new window, set the CDEV_NAME_SERVER and the CDEVDDL environment variables as previously described. The test client may then be started by typing the following command "TestProgram".

5h.

Examine Test Server and Test Client output. The server and the client should periodically print a line indicating that the packets that they are exchanging are correctly matched. If a mismatch occurs, both sides of the connection will print out a verbose description of what differences were detected.

5i.

Terminate the Test Server and the Test Client. The TestServer and TestProgram applications are terminated using CTRL-C. When the applications are terminated, they should display a disconnecting message and exit gracefully.

3.

The Reflector Server - A Simple Client/Server System

Overview

The Reflector client/server system is a simple CDEV service that returns the cdevData object unmodified to the caller. The Reflector server can be used as a skeleton for any other server that the developer may wish to create. The source code that is provided in the following sections is available in text form in the examples sub- directory of the cdevGenericServer directory tree. A more complex example is provided in section 11 of this document.

Reflector Server Source Code

The server for the Reflector system is instituted as a single C++ file. The source code for this application is listed below.

Figure 10: ReflectorServer.cc - Source Code for the Reflector Server

#include <cdevServer.h>
 
// ******************************************************************
// * class ReflectorServer:
// *   This is the server class for the reflector. It simply
// *   receives messages from a client and immediately returns them.
// *
// *   The constructor passes the domain, server, port and rate to the
// *   underlying cdevServer class to be processed. The cdevServer
// *   constructor will add this server to the Name Server and will 
// *   begin processing messages when the cdevServer::runServer() 
// *   method is executed.
// *
// *   The processMessages method is the servers interface to the 
// *   world... Each time a complete message is received or the time 
// *   specified in rate expires, that method will be called.
// ******************************************************************
class ReflectorServer : public cdevServer
{
public:
   ReflectorServer ( char *domain, char *server, 
                  unsigned int port, double rate )
      : cdevServer(domain, server, port, rate)
      {
      }
 
   virtual void processMessages ( void )
      {
      cdevMessage * message;
      while(dequeue(message)==0)
         {
         enqueue(message);
         delete message;
         }
      }
};
 
void main()
{
ReflectorServer server("REFLECTOR", "TestServerX", 9120, 60);
cdevServer::runServer();
}
			

ReflectorServer Header Files

In the source code for the Reflector server, the only header file that must be included is the one for the cdevServer class. This header contains all of the definition information that is required for the Adaptive Communications Environment (ACE) and the CDEV Linear Internet Protocol.

The ReflectorServer Class

The ReflectorServer class inherits directly from the cdevServer class. Because cdevServer defines all of the functionality necessary to establish a listening socket and accept connections, the developers start-up is limited to initializing the cdevServer class object with the domain name, server name, listening socket number and the time-out rate.

The developer is required to create a processMessages method which will perform whatever message processing that is required of the server. In this case, the processMessages method will merely remove an entry from the queue and then re- enqueue it for return to the client. Note that the enqueue method does not delete the cdevMessage object, so it is the responsibility of the developer to delete the cdevMessage object when it is no longer needed.

The main Function

The main function is responsible for starting the server when the application is started. In order to perform this task, main must first create a new ReflectorServer object. The ReflectorServer in this example has the Name Server domain "REFLECTOR" and the server name "TestServerX". It will be listening for connections on socket 9120 and will automatically process messages at least once every 60 seconds.

When the ReflectorServer was created it automatically registered itself with the ACE Reactor that is embedded in the cdevServer class. In order to begin accepting connections and processing messages the main function must call the static runServer method of the cdevServer class. This method will continue servicing requests until the static Finished flag of the cdevServer class is set to non-zero.

The ReflectorService Source Code

The ReflectorService is the CDEV interface to the ReflectorServer that is described above. The source code for the ReflectorServer is implemented as a single source file and its associated header file. The source code for the ReflectorService is as follows.

Figure 11: ReflectorService.h - Header File for the Reflector Service

#include <cdevClientService.h>
 
// ******************************************************************
// * Function called to create initial instance of ReflectorService
// ******************************************************************
extern "C" cdevService *newReflectorService ( char *, cdevSystem *);
 
// ******************************************************************
// * class ReflectorService :
// *   This class simply inherits from the cdevClientService and must 
// *   define only a constructor and destructor.
// ******************************************************************
class ReflectorService : public cdevClientService
{
public:
   ReflectorService (   char * name, cdevSystem & system =
      cdevSystem::defaultSystem());   
protected:
   virtual ~ReflectorService ( void ) {};
};
			

Figure 12: ReflectorService.cc - Source Code for the Reflector Service

#include <ReflectorService.h>
 
// ******************************************************************
// * newReflectorService:
// *   This function will be called by the cdevSystem object to create 
// *   an initial instance of the ReflectorService.
// ******************************************************************
extern "C" cdevService * newReflectorService 
   (char * name, cdevSystem * system)
   {
   return new ReflectorService(name, *system);
   }
 
// ******************************************************************
// * ReflectorService::ReflectorService :
// *   This is the constructor for the ReflectorService.  It 
// *   initializes the underlying cdevClientService by specifying 
// *   that it is in the domain of REFLECTOR.
// ******************************************************************
ReflectorService::ReflectorService 
   ( char * name, cdevSystem & system)
   : cdevClientService("REFLECTOR", name, system) 
   {
   system.reportError(CDEV_SEVERITY_INFO, "ReflectorService", NULL, 
            "Constructing a new ReflectorService"); 
   }
			

The ReflectorService.h Header File

While the server is not required to have a specific header file, a CDEV service must have a header file that may be used to create a loader for the archive version of the library. This file is always named xxxxxService.h, where xxxxx is the name of the service as it will be specified in the CDEV DDL file. This file must contain the complete class definition for the service class.

The newReflector Service Function

Each service in CDEV must have a function that the cdevSystem object can call to create the initial instance of the object. In the case of the ReflectorService, this method will create a new instance of the ReflectorService using the provided name and cdevSystem object. This new object will then be returned as a pointer to a cdevService object.

The ReflectorService Class

Because of the simplicity of the ReflectorService, all of the functionality of this class is inherited from the cdevClientService class. The ReflectorService class is only required to initialize its parent classes to be fully operational.

The CDEV DDL File

After compiling this source code into a server application and a CDEV shared library using the makefile that is provided in the examples sub-directory, the developer is ready to generate a CDEV DDL file that will map certain device/message combinations to the Reflector service. The following simple CDEV DDL file can be used to map device "device1" and message "get attrib1" to the Reflector Service. Note that by entering the server tag in the service data section, the default server name that the message will be sent to may be specified. In this case all messages associated with the "attrib1" attribute will be sent to "TestServerX".

Figure 13: Reflector.ddl - A Simple CDEV DDL File

service Reflector 
   {
   tags {server}
   }
 
class Reflectors 
   {
       verbs {get}
   attributes 
      {
      attrib1     Reflector {server=TestServerX};
      }
   }
 
Reflectors :
   device1,
;
			

Testing the Reflector Server

After compiling the server and the service components of the Reflector system, the developer can test the functionality of the client/server application by performing the following steps.

1.

Start the Name Server.

2.

Set the CDEV_NAME_SERVER environment variable in the shell where you will execute the server and the client to indicate the host where you started the Name Server. For instance: setenv CDEV_NAME_SERVER cebaf1.cebaf.gov.

3.

Set the CDEVSHOBJ environment variable in the shell where you will start the client application to indicate the directory where the ReflectorService.so file is stored.

4.

Set the CDEVDDL environment variable in the shell where you will start the client application to indicate the absolute path to the CDEV DDL file where the Reflector definitions have been created.

5.

Start the server.

6.

Start the cdevUtil application that is provided with the CDEV distribution and send messages to the server by typing: device1 get attrib1. You may want to enter additional output code in the processMessages method of the server to report each time a message is received.

4.

Server Class Hierarchy

Server Classes

The server side of the CDEV Generic Server Engine library is composed of a series of classes that are used in conjunction with the ACE Reactor class to provide event driven socket management. The following diagram shows an object diagram of the classes that are used on the server side of the connection.

Figure 1: Object Hierarchy of Server Classes

FifoQueue Class

This class is a simple queue that is used to enqueue inbound messages that are received from a socket. Because all messages will be processed by the same method, there is only one FifoQueue object that is used by all client sockets. This object resides in the cdevSessionManager class.

MultiQueue Class

A MultiQueue object is a special type of FifoQueue that allows the caller to create an object that is to be placed into the queue and then place it into several queues at once. If the message is removed from any queue, it will automatically be removed from all other queues where it exists. This mechanism is used to provide the capability of removing all of a specific client's outbound packets without stepping through all of the packets in the associated socket's queue.

ClientSession Class

The ClientSession class inherits its queue functionality from the MultiQueue class. It is used to hold all outbound packets that are associated with a specific client identifier. The ClientSession object also holds supplemental data that the cdevSessionManager will need to manage the client. This class be subclassed by the developer in order to associate more data with the client identifier. The following information is stored in the ClientSession object:

Attributes of the ClientSession Class

localID

short localID;

This is the client identifier that will be used on the server to uniquely identify the client.

clientID

int clientID;

This is the client identifier that was provided by the client combined with the socket identifier.

socketID

int socketID;

This is the socket identifier (file descriptor) to which the client is connected.

SocketSession Class

The SocketSession class inherits its functionality from the MultiQueue class. It is used to hold all packets that are destined for a specific socket. The SocketSession object is also used to store supplemental data that the cdevSessionManager will need to maintain the connection. This class be subclassed by the developer in order to associate more data with the socket identifier. The following information is stored in the SocketSession object:

Attributes of the SocketSession Class

socketID

int socketID;

This is the socket identifier (file descriptor) to which the remote client is attached.

ClientAcceptor Class

The ClientAcceptor class is used by the ACE Reactor to listen to the server socket and accept each inbound client connection. When a connection is accepted, this class will create a ClientHandler object that will manage the connection throughout its lifetime.

SocketReader Class

The SocketReader class has the embedded mechanisms to read buffered packets from a socket. The ClientHandler inherits the functionality of this class to read data that is received on its associated socket.

SocketWriter Class

The SocketWriter class has the embedded mechanisms to write buffered packets to a socket. The class maintains a 56 kilobyte buffer that it uses to enqueue as many outbound messages as possible before executing a network write. The ClientHandler inherits the functionality of this class to write data to its associated socket.

ClientHandler Class

A ClientHandler object is created each time a new connection is accepted by the server. This class is used by the ACE Reactor to manage the input and output events on the specific socket. When data is received from the socket by the handle_input method, the ClientHandler object will enqueue the inbound packet in the FifoQueue provided by the cdevSessionManager class. When the cdevSessionManager class enqueues outbound packets, the handle_output method of the ClientHandler class will write them to the socket using as many write operations as required to transmit all data.

When the ClientHandler object is destroyed it will notify the cdevSessionManager object which will remove its associated queues and will remove it from the ACE Reactor.

cdevSessionMan ager Class

The cdevSessionManager class maintains all of the queues, ClientSession and SocketSession objects that are used to operate a server. This class also defines the enqueue and dequeue methods that are used by the cdevServer to obtain inbound packets and to submit outbound packets.

cdevServer Class

The cdevServer class inherits the queue management functionality that is provided by the cdevSessionManager class and then implements the ClientAcceptor and ClientHandler classes to accept and process connections. The cdevServer class also introduces the concept of timed execution of the server function and automatic registration of the server with the CDEV Name Server.

In order to construct a new CDEV Server application, the developer only needs to inherit his server class from the cdevServer class and then define the processMessages method. This method will be called whenever the server timer expires or when data is ready to be processed in the inbound queue. Once called the processMessages method should use the dequeue method to remove the inbound cdevMessage object, process the message, and then use the enqueue method to return the processed cdevMessage object to the client.

The encodePacket and decodePacket methods of this class are responsible for coordinating the tables of context objects, performing tag mapping and converting between the local client identifier and the foreign client identifier.

5.

Client Class Hierarchy

Client Classes

The client side of the CDEV Generic Server Engine consists of a collection of classes that are used in conjunction with the CDEV service architecture and the ACE Reactor to provide pollable event driven behavior. The following diagram shows the object structure of the classes used by the client.

Figure 2: Object Hierarchy of Client Classes

SocketReader Class

The SocketReader class has the embedded mechanisms to read buffered packets from a socket. The ServerHandler inherits the functionality of this class to read data that is received on its associated socket.

SocketWriter Class

The SocketWriter class has the embedded mechanisms to write buffered packets to a socket. The class maintains a 56 kilobyte buffer that it uses to enqueue as many outbound messages as possible before executing a network write. The ServerHandler inherits the functionality of this class to write data to its associated socket.

ServerHandler Class

A ServerHandler object is created for each server that the cdevServerInterface wishes to communicate with. This object has an embedded FifoQueue object that is used to store the outbound packets until the ServerHandler's data is flushed. If the ServerHandler receives a sufficient number of packets or volume of data it will automatically flush its buffer to the socket. The ServerHandler inherits much of its communications functionality from the SocketReader and SocketWriter classes which provide buffered communications methods.

The cdevClientRequestObject may obtain a pointer to the ServerHandler that is associated with the server that it is communicating with. By referencing this pointer when enqueueing messages to the server through the cdevService, the request object can increase its performance significantly because it does not have to locate the associated ServerHandler on each transmission.

A cdevClientRequestObject that is utilizing a ServerHandler will register itself in a list of ServerHandlerCallback objects that are maintained in the ServerHandler object. When the ServerHandler is destroyed it will notify each ServerHandlerCallback object in the list to allow them to clear their pointers to it, avoiding the inadvertent use of an invalid object.

ServerHandler Callback Class

The ServerHandlerCallback class is a virtual base class that any class that uses a ServerHandler object may use to detect when the object is destroyed. When an object that is inherited from this class is registered with the ServerHandler, it will be called prior to deleting the ServerHandler object. The inherited object should then set the associated ServerHandler pointer to NULL to prevent inadvertent access to a deleted object. The cdevClientRequestObject inherits from this class in order to support this functionality.

ServerConnection List Class

The ServerConnectionList is a table of all ServerHandler objects that are currently connected to servers. The cdevServerInterface uses this table to locate a ServerHandler by the name of its associated server. This table prevents multiple connections from inadvertently being established to the same server.

cdevServerInter face Class

This class has a ServerConnectionList that references all ServerHandlers that are connected to servers for the specific service. This object provides the mechanisms that are used to enqueue, dequeue, flush, poll and pend on the outbound connections.

The cdevServerInterface class contains an ACE Reactor that is used to respond to input/output events that occur on the sockets within the ServerHandlers. Because this Reactor is static within the cdevServerInterface class, it will handle events for all of the server connections in all of the services that are inherited from it when it is called.

cdevClientRe questObject Class

This class inherits the majority of its functionality from, the cdevRequestObject class and is used to associate a device with a specific message. The identity of the server that supports the specific device/message combination may be specified in several ways: through the server tag in the context, through the CDEV DDL file, or by the server specified by a prior call to set default. If a specific server has been named, the cdevClientRequestObject will obtain a pointer to the associated ServerHandler object and will use that as a refer