The Client/Server Communication Component (CSCC) is a very simple, but powerful library, entirely written in Java. It can be used for transmitting messages containing arbitrary data asynchronously between several clients and/or a server. In contrast to Remote Method Invocation, the CSCC should be easy to use and a lightweight alternative for communication.

Figure 1: Several clients might communicate with and over a central server.
The server can provide a service for the client, e.g. it may strore centralized data. The clients are able to communicate with the central server or other registered clients (see Fig. 1). In a non-synchronized system, asynchronous communication can cause concurrency problems. The CSCC provides an automatic synchronization mechanism for handling this problem. The mechanism is transparent for the user of the CSCC and therefore the component is easy to use. We distinguish between two different type of communication events that can occur at the clients or the server, respectively. The first one is the so-called data event which is delivered as soon as a data package is received at the target. It is representedby an object of the class {@link ch.unizh.ifi.comm.DataEvent}. The second event type occurs if one or more nodes participating the communication are informed about the state of the coommunication, e.g. if a client loses the connection or a new client joins communication. The server has to implement a logic interpreting the events. Events might be processed by the server or they might be sent directly to one or more clients.
The following functionality is provided by the CSCC:
The following classes and interfaces provide the functionality of the C/S communication component:
Additional information is provided by these packages. The following UML class diagramm shows the public classes of the package {@link ch.unizh.ifi.comm}:

Figure 2: A class diagramm of all classes that build the interface of the CSCC.
Receiving data events can be handled in the same way by the client, as well the server implementation. In the CSCC, there are two options for receiving data events:
As soon as a data event from a client is received by the server, the server assigns automatically the client identification object to the particular data event. The current implementation uses a {@link java.lang.Integer} object containing a communication system wide unique number as client identification object. This object can be used to identify the client and to relate messages to the client.
Sending data from the one client participant of the system to a target participant is an easy task. After instantiating a {@link ch.unizh.ifi.comm.ClientConnectionManager} object at the client and opening a connection to a server (by using the method {@link ch.unizh.ifi.comm.ClientConnectionManager#open(String name)}), data can be sent to the target by using the method {@link ch.unizh.ifi.comm.ClientConnectionManager#sendDataEvent(DataEvent de)}. The given {@link ch.unizh.ifi.comm.DataEvent} contains the data which is asynchronously transmitted to the target.
There are two methods to send {@link ch.unizh.ifi.comm.DataEvent} objects to the client. The first method is used to broadcast an event object to all connected clients. This is done by using the {@link ch.unizh.ifi.comm.ServerConnectionManager#sendBroadCastEvent(DataEvent de)} method. The method {@link ch.unizh.ifi.comm.ServerConnectionManager#sendDataEvent(DataEvent de, Object clientId)} sends the message to client, which is identified by the parameter objectId. objectID is an identification object provided automatically by the server (see also Communication Events).
This event type can be queried by calling the method {@link ch.unizh.ifi.comm.CommunicationEvent#getEventId()}. For receiving communication events, an object of the type {@link ch.unizh.ifi.comm.CommunicationEventObserver} has to be added to the communication observer list. This is done by calling the method {@link ch.unizh.ifi.comm.ServerCommunicationManager#addObserver(ch.unizh.ifi.comm.CommunicationEventObserver o)} for the server side communication observer, respectively {@link ch.unizh.ifi.comm.ClientCommunicationManager#addObserver(ch.unizh.ifi.comm.CommunicationEventObserver o)} for the client side communication observer.
Under some circumstances, it is necessary to identify the connection of the client which caused the
event by other participants of the communication. Therefore the method {@link ch.unizh.ifi.comm.CommunicationEvent#getData()} returns an identifier object. This object is used to identify the client uniquely. In this implementation this object is a {@link java.lang.Integer} object containing a unique integer number. The
events occuring at the server which contain client ids are: {@link ch.unizh.ifi.comm.CommunicationEvent#CONNECTION_ESTABLISHED}, {@link
ch.unizh.ifi.comm.CommunicationEvent#CONNECTION_BROKEN} and {@link ch.unizh.ifi.comm.CommunicationEvent# CONNECTION_CLOSED}.
The following sections contain a short tutorial describing the usage of the library in push mode:
For creating a server, follow these steps:
ServerConnectionManager scm = new ServerConnectionManager(2510);
scm.beginListening();
public class MyServerDataEventReceiver implements DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de) {
// here follows some code, handling the receiving of the DataEvent objects
}
}
public class MyServerCommunicationEventReceiver implements CommunicationEventObserver {
...
public void void receiveEvent(CommunicationEvent ce) {
// here follows some code, handling the receiving of the CommunicationEvent objects
}
}
For creating a client, follow these steps:
ClientConnectionManager ccm = new ClientConnectionManager(2510);
ccm.open("127.0.0.1");
public class MyClientDataEventReceiver implements DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de) {
// here follows some code, hanlding the receiving of the DataEvent objects
}
}public class MyClientCommunicationEventReceiver implements CommunicationEventObserver {
...
public void void receiveEvent(CommunicationEvent ce) {
// here follows some code, handling the receiving of the CommunicationEvent objects
}
}
A full-fledged example of a client/server application can look like the following:
/* Server */
import ch.unizh.ifi.comm.ServerConnectionManager;
import ch.unizh.ifi.comm.DataEventReceivingObserver;
import ch.unizh.ifi.comm.DataEvent;
import ch.unizh.ifi.comm.CommunicationEventObserver;
import ch.unizh.ifi.comm.CommunicationEvent;
// The server incorporates also the data observer and the communication
// observer interface
public class TestServer implements DataEventReceivingObserver, CommunicationEventObserver {
// provides the server connection
ServerConnectionManager scm;
public TestServer() {
scm = new ServerConnectionManager(2510);
// add comm. observer
scm.addObserver((CommunicationEventObserver)this);
// add data event observer
scm.addObserver((DataEventReceivingObserver)this);
// start listening for new connections
scm.beginListening();
}
public void receiveEvent(DataEvent de) {
// data event from the client, just print out the content
System.out.println("Client says " + de.getData().toString());
scm.sendBroadCastEvent(new DataEvent(new Integer(1),"Pong"));
}
// receives all the communication events
public void receiveEvent(CommunicationEvent ce) {
String data = "";
// if the communication event contains data
if (ce.getData() == null) { // identifying the client
System.out.println("No additional data about comminication event");
} else {
// there is a description about the client --> client number.
System.out.println("Number of client: " + ce.getData());
data = ce.getData().toString();
}
// ask for all possible communication events.
// print the event which occurred
switch (ce.getEventId()) {
case (CommunicationEvent.CONNECTION_ESTABLISHED):
System.out.println("connection opened!");
break;
case (CommunicationEvent.CONNECTION_BROKEN):
System.out.println("connection broken");
break;
case (CommunicationEvent.CONNECTION_CLOSED):
System.out.println("connection closed");
break;
case (CommunicationEvent.CONNECTION_START_LISTENING):
System.out.println("start listening");
break;
case (CommunicationEvent.CONNECTION_STOP_LISTENING):
System.out.println("stop listening");
break;
}
}
// starts up the server
public static void main(String[] args) {
TestServer t = new TestServer();
}
}
/* Client */
import ch.unizh.ifi.comm.ClientConnectionManager;
import ch.unizh.ifi.comm.DataEvent;
import ch.unizh.ifi.comm.DataEventReceivingObserver;
import ch.unizh.ifi.comm.CommunicationEvent;
import ch.unizh.ifi.comm.CommunicationEventObserver;
// The server incorporates also the data observer interface and the communication
// observer interface
public class TestClient implements DataEventReceivingObserver, CommunicationEventObserver {
// client connection manager
ClientConnectionManager ccm;
TestClient() {
// client connection manager,
preparing for the connection to the server
ccm = new ClientConnectionManager(2510);
// add as comm. event observer
ccm.addObserver((CommunicationEventObserver)this);
// add as data event observer
ccm.addObserver((DataEventReceivingObserver)this);
// open connection to server, must run on the same machine
ccm.open("127.0.0.1");
// send first event to the server.
ccm.sendDataEvent(new DataEvent(new Integer(1), "Ping"));
}
// starts up the client
public static void main(String[] args) {
TestClient tc = new TestClient();
}
// receives all data events
public void receiveEvent(DataEvent de) {
// received data from the server
System.out.println("Server says " + de.getData().toString());
// send another ping
ccm.sendDataEvent(new DataEvent(new Integer(1), "Ping"));
}
// receives all communication events
public void receiveEvent(CommunicationEvent ce) {
switch (ce.getEventId()) {
case (CommunicationEvent.CONNECTION_ESTABLISHED):
System.out.println("connection opened!");
break;
case (CommunicationEvent.CONNECTION_BROKEN):
System.out.println("connection broken");
break;
case (CommunicationEvent.CONNECTION_CLOSED):
System.out.println("connection closed");
break;
case (CommunicationEvent.CONNECTION_START_LISTENING):
System.out.println("start listening");
break;
case (CommunicationEvent.CONNECTION_STOP_LISTENING):
System.out.println("stop listening");
break;
}
}
}
The implemented protocol in this case is very simple: The client sends a ping message to the server, the server prints the message and returns a pong message. Every time the client receives a messages, it sends a ping to the server. Therefore this ends in an endless communication, with the client sending pings and the server answering with pongs.
Further examples using the CSCC can be found in the source code packages {@link ch.unizh.ifi.comm.test}, {@link ch.unizh.ifi.comm.examples.chatsystem} and {@link ch.unizh.ifi.comm.examples.simplesystem}.
After getting the source codes, the source codes can be compiled by running ant in the root of the project directory. Use the following ant targets:
| Ant Target | Description |
| clean | Cleans the build directories |
| clean_compile | Cleans the build directory and compiles the source code |
| compile | Compiles the source code |
| cvs-update | Updates project (src dir) |
| doall | Does all the tasks |
| javadoc | Generates the API documentation |
| javadoc-private | Generates the API documentation with containing also the description of private elements |
| prepare | Prepares the execution structures |
| release | Builds a .jar file which is ready to use as a library in the class path. |
| run-client | Runs the example chat program (client) |
| run-server | Runs the example chat program (server) |
| Client | The cllient is a consumer of a service which is provided by the server. The client has to connect over a remote connection to the server for getting the provided services. |
| Client Identification Object | The identification object is used at the server side to retrieve realte a client to a specific data or communication event. For the clients, it's sometimes necessary to know which client is the originator of a communication or data event. The client that caused a communication event is identified by calling the method {@link ch.unizh.ifi.comm.CommunicationEvent#getEventId()}. |
| Communication Event | The event that occurs, when the state of the communication connection changes. |
| Data Event | The event that occurs, every time data is received from one of the communication partner. |
| Process/Thread | A process/thread is the execution of code. Several processes can run in parallel or concurrently. |
| Server | The server provides remote services to one or more clients. |
| $Date: 2006/12/02 16:19:21 $ | ||||||||||||||||||||||||||||||
| $Author: smeier $ | ||||||||||||||||||||||||||||||
| $Revision: 1.1 $ | ||||||||||||||||||||||||||||||
Project History:
| ||||||||||||||||||||||||||||||