|
||||||||||
PREV NEXT | FRAMES NO FRAMES |
See
Description
Packages | |
net.sf.cscc | The package net.sf.cscc contains the classes and interfaces for the Client/Server Communication Component (CSCC). |
net.sf.cscc.examples.chatsystem | The package net.sf.cscc.examples.chatsystem contains a Server and a Client of a chatsystem demonstrating the usage of Client/Server Communication Component (CSCC). |
net.sf.cscc.examples.simplesystem | The package net.sf.cscc.examples.simplesystem contains a small application demonstrating how to send data from multiple clients to a server using the Client/Server Communication Component (CSCC). |
net.sf.cscc.test |
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 using a queuing of
messages. The
mechanism is transparent for the user of the CSCC and therefore the
component is easy
to use.
There are two different types of communication events that
can occur at the client- or the server-side. 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 represented by an object of the class DataEvent
.
The second event type occurs if one or more nodes in the communication
network are informed about the state of the coommunication, e.g. if a
client loses the connection or a new client joins to the server.
The
server has to implement a logic for interpreting the events. Events
might be
processed by the server or they might be forwarded to one or more
clients. Thus, the CSCC provides the communication between one server
and one to several clients. However, high-level protocol has to be
implemented by the component user.
The following functionality is provided by the CSCC:
ServerConnectionManager
)
ClientConnectionManager
)
The following classes and interfaces provide the functionality of the C/S communication component:
ClientConnectionManager
: The main class for
handling the connection to a server at the client-side.CommunicationEvent
: Main class representing
the event occurring when a status change in the communication happens.CommunicationEventObserver
: The observer
interface for communication events.DataEvent
: This class carries the data
transmitted over the network.DataEventBaseObserver
: The basic observer
interface for the occuring data event.DataEventObserver
: The data event observer
interface.DataEventReceivingObserver
: Another interface
for observing data events.ServerConnectionManager
: The main class for
handling the connections at the server-side.Additional information is provided by these packages. The following UML class diagramm shows the public classes of the package net.sf.cscc:
Figure 2: A class diagramm of all classes that build the interface of the CSCC.
The receiving of data events can be handled in the same way at the client as well at the server implementation. In the CSCC, there are two options for receiving data events:
ServerConnectionManager.getDataEvent()
, ServerConnectionManager.hasDataEvents()
, ServerConnectionManager.receiveDataEvent()
, ServerConnectionManager.removeDataEvent()
. DataEventObserver
or
DataEventReceivingObserver
. These interfaces are
called each time a data or a communication event occurs. DataEventObserver
is used by the pull mode and just
receives
the event, but does not deliver the DataEvent
object
directly. When implementing the DataEventObserver interface, a
particular class has to fetch 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.
Furthermore, additional
threads have to be introduced for checking the queue after a certain
time interval, therefore the usage of the CSCC in the pull mode is
discouraged. Moreover, the pull mode is not very convenient and
efficient and it may cause a synchronization problem. DataEventReceivingObserver
. This
interface delivers the data event with the notification of the data
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. Thus in the following,
only the use of the push mode of the CSCC is discussed.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 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 one participating client to another is easy. After
instantiating a ClientConnectionManager
object at
the client's side and opening a connection to a server (by using the
method
ClientConnectionManager.open(String name)
), the 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 different methods to send DataEvent
objects
to the clients. 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. The parameter 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_ESTABLISHED
CommunicationEvent.CONNECTION_BROKEN
CommunicationEvent.CONNECTION_CLOSED
CommunicationEvent.CONNECTION_START_LISTENING
CommunicationEvent.CONNECTION_STOP_LISTENING
The 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 ServerConnectionManager.addObserver(net.sf.cscc.CommunicationEventObserver
o)
for registering the
server-side communication observer and by calling the method ClientConnectionManager.addObserver(net.sf.cscc.CommunicationEventObserver
o)
for registering the client-side communication observer respectively.
Under some circumstances, it is necessary to identify the client
which caused the communication event. 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 denoting the client. The
events occuring contain client ids are: CommunicationEvent.CONNECTION_ESTABLISHED
, CommunicationEvent.CONNECTION_BROKEN
and CONNECTION_CLOSED.
The following sections contain a short tutorial describing the use of the library in push mode:
For creating a server, follow these steps:
ServerConnectionManager
object. An object of this class handles the communication of a server:
ServerConnectionManager scm = new ServerConnectionManager(2510);
This statement instantiates a newServerConnectionManager
object which uses the TCP/IP port 2510 listening for client connections.
scm.beginListening();
DataEventReceivingObserver
:public class
MyServerDataEventReceiver implements
DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de)
{
// here follows some code,
handling the receiving of the DataEvent objects
}
}
scm.addObserver(new MyServerDataEventReceiver());
CommunicationEventObserver
has to be implemented:public class MyServerCommunicationEventReceiver implements
CommunicationEventObserver {
...
public void void
receiveEvent(CommunicationEvent ce) {
// here follows some code,
handling the receiving of the CommunicationEvent objects
}
}
scm.addObserver(new MyServerDataEventReceiver());
For creating a client, these steps have to be followed:
ClientConnectionManager
object has to be instantiated. An object of this class handles the
communication between a
client and a server:
ClientConnectionManager ccm = new ClientConnectionManager(2510);
This statement instantiates a newClientConnectionManager
object which uses the TCP/IP port 2510 for connections to the server.
ccm.open("127.0.0.1");
DataEventReceivingObserver
:public class MyClientDataEventReceiver implements
DataEventReceivingObserver {
...
public void receiveEvent(DataEvent de)
{
// here follows some code,
hanlding the receiving of the DataEvent objects
}
}
scm.addObserver(new MyClientDataEventReceiver());
CommunicationEventObserver
has to be implemented:public class MyClientCommunicationEventReceiver implements
CommunicationEventObserver {
...
public void void
receiveEvent(CommunicationEvent ce) {
// here follows some code,
handling the receiving of the CommunicationEvent objects
}
}
scm.addObserver(new MyClientCommunicationEventReceiver());
A full example of a client/server application looks for instance like the following:
/* Server */
import net.sf.cscc.ServerConnectionManager;
import net.sf.cscc.DataEventReceivingObserver;
import net.sf.cscc.DataEvent;
import net.sf.cscc.CommunicationEventObserver;
import net.sf.cscc.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 net.sf.cscc.ClientConnectionManager;
import net.sf.cscc.DataEvent;
import net.sf.cscc.DataEventReceivingObserver;
import net.sf.cscc.CommunicationEvent;
import net.sf.cscc.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 protocol implemented in this example is very simple: The client sends a ping message to the server, the server prints the message and returns a pong message to the client. Every time the client receives a messages, it sends a ping to the server. Therefore client and the server sends endlessly pings and pongs respectively.
Further examples using the CSCC can be found in the source code packages net.sf.cscc.test, net.sf.cscc.examples.chatsystem and net.sf.cscc.examples.simplesystem.
After getting the source code project, the source code can be compiled by running ant in the root of the project directory. The following ant targets can be used:
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 client is a consumer of a service which is provided by the server. The client has to connect over a connection to the server for getting the provided services. |
Client Identification Object | The identification object is used at the server
side to retrieve the client from which a specific data or communication
event originates. The client id can of a communication event can be
retrieved by calling the method
CommunicationEvent.getEventId() . |
Communication Event | A communication event occurs when the state of the communication connection changes. |
Data Event | A data event occurs every time data is received from one of the communication partners. |
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: 2007/07/02 21:26:16 $ | ||||||||||||||||||||||||||||||||||||
$Author: reode_orm $ | ||||||||||||||||||||||||||||||||||||
$Revision: 1.2 $ | ||||||||||||||||||||||||||||||||||||
Project History:
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||
PREV NEXT | FRAMES NO FRAMES |