|
||||||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||||
See
Description
| Packages | |
| ch.unizh.ifi.comm | The package ch.unizh.ifi.comm contains the classes and interfaces for the Client/Server Communication Component (CSCC). |
| ch.unizh.ifi.comm.examples.chatsystem | The package ch.unizh.ifi.comm.examples.chatsystem contains a Server and a Client of a chatsystem demonstrating the usage of Client/Server Communication Component (CSCC). |
| ch.unizh.ifi.comm.examples.simplesystem | The package ch.unizh.ifi.comm.examples.simplesystem contains a small application demonstrating how to send data from multiple clients to a server using the Client/Server Communication Component (CSCC). |
| ch.unizh.ifi.comm.test | |
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 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:
ServerConnectionManager)
ClientConnectionManager)
The following classes and interfaces provide the functionality of the C/S communication component:
ClientConnectionManagerCommunicationEventCommunicationEventObserverDataEventDataEventBaseObserverDataEventObserverDataEventReceivingObserverServerConnectionManagerAdditional information is provided by these packages. The following UML class diagramm shows the public classes of the package 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:
ServerConnectionManager.getDataEvent(), ServerConnectionManager.hasDataEvents(), ServerConnectionManager.receiveDataEvent(), ServerConnectionManager.removeDataEvent().
Due to the fact that additional threads have to be introduced for checking
the queue after a certain time interval, the usage of the CSCC in the pull
mode is discouraged. Additionally, this mode is not very convenient and
efficient any may cause a synchronization problem. DataEventObserver or DataEventReceivingObserver. These interfaces
are called each time a data or a communication event occurs. This mode of
usage is recommended to the user of the CSCC. The difference between these both interfaces is, that the interface DataEventObserver just receives the event, but does not get the
DataEvent object directly. Implementing the DataEventObserver
interface, a particular class has to get the event manually out of the
event queue. Therefore the implementing class is responsible, that the event is removed from the queue, after all
observers received the event, which complicates the usage of the CSCC. Therefore the implementation of the interface DataEventReceivingObserver should be preferred. This interface
delivers the data event when the notification of the event occurs. The implementation
of the DataEventReceivingObserver interface by all
participants of the communication ensures that all observers consume the data events
immediately after their occurence and therefore, the data event is automatically removed from the data event queue.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 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 ClientConnectionManager object at the client and opening a connection to a server (by using the method ClientConnectionManager.open(String name)), data can be sent to the
target by using the method ClientConnectionManager.sendDataEvent(DataEvent de). The given DataEvent contains the data which is asynchronously transmitted to the
target.
There are two methods to send 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 ServerConnectionManager.sendBroadCastEvent(DataEvent de) method. The method 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).
CommunicationEvent.
Five different types of events can occur which are described by the following
constants:
CommunicationEvent.CONNECTION_ESTABLISHEDCommunicationEvent.CONNECTION_BROKENCommunicationEvent.CONNECTION_CLOSEDCommunicationEvent.CONNECTION_START_LISTENINGCommunicationEvent.CONNECTION_STOP_LISTENINGThis event type can be queried by calling the method CommunicationEvent.getEventId(). For receiving
communication events, an object of the type CommunicationEventObserver has to be added to the communication observer
list. This is done by calling the method ch.unizh.ifi.comm.ServerCommunicationManager#addObserver(ch.unizh.ifi.comm.CommunicationEventObserver o) for the
server side communication observer, respectively 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 CommunicationEvent.getData() returns an identifier object. This object is used to identify the client uniquely. In this implementation this object is a Integer object containing a unique integer number. The
events occuring at the server which contain client ids are: CommunicationEvent.CONNECTION_ESTABLISHED, CommunicationEvent.CONNECTION_BROKEN and 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 object. An object of this class handles the communication
from a server:
ServerConnectionManager scm = new ServerConnectionManager(2510);
ServerConnectionManagerobject which uses the TCP/IP port 2510 listening for
client connections.scm.beginListening();
DataEventReceivingObserver, in the class which receives the data
events:public class MyServerDataEventReceiver implements DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de) {
// here follows some code, handling the receiving of the DataEvent objects
}
}
CommunicationEventObserver: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 object. An object of this class handles the communication
between a
client and a server:
ClientConnectionManager ccm = new ClientConnectionManager(2510);
ClientConnectionManagerobject which uses the TCP/IP port 2510 for
connections to the server.ccm.open("127.0.0.1");
DataEventReceivingObserver in the class which
should receive the data
events:public class MyClientDataEventReceiver implements DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de) {
// here follows some code, hanlding the receiving of the DataEvent objects
}
}CommunicationEventObserver: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 ch.unizh.ifi.comm.test, ch.unizh.ifi.comm.examples.chatsystem and 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 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/11/28 11:01:12 $ | ||||||||||||||||||||||||||||||
| $Author: smeier $ | ||||||||||||||||||||||||||||||
| $Revision: 1.1 $ | ||||||||||||||||||||||||||||||
Project History:
| ||||||||||||||||||||||||||||||
|
||||||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||||