What is the value of unshared information? Not much. The thought
that I just had, but
didn't relate to anyone, may die as soon as I forget it. The communication,
exchange of
information, is a fundamental factor that made us who we are today.
It is by interchange
of ideas that we grow and develop.
In the early days of computing, when CPU power was scarce, the concept
of distributed computing was born. Not necessarily to share the information,
just to speed up computation.
Ever since, computer science was infected and fascinated with issues
in distributed computing. How is information transferred? What is the protocol?
Is it safe/secure? What
is the capacity of transformation channel? What is the rate of transformation
of data?
What are the functions of the participants on different ends? These
questions shaped
the field of distributed computing to be a sophisticated and inextricable
part of information
technology. Two core ways to pass the information around come to
mind - client/server
and peer-to-peer.
As many of you know, the idea behind client/server programming is
to have lightweight
programs sitting on user computers (usually PCs) communicate with
powerful servers.
Client programs, when they startup, connect themselves to servers,
authenticate and ask for
some profile-type data. The role of server is store large amounts
of information,
allow the share of this information when appropriate, perform significant
computations.
These days you would find several multi tier client/server architectures.
The financial
industry is probably still dominated by 3-tier setups.
Another distributed model is peer-to-peer. Unlike client/server,
this model assumes that
participating computers have equal power and capacity. This model,
is probably close
to idea of propagating information through self-organizing networks
- the once we find
so many in nature. Basically, peer-to-peer network is organized
in a graph. There are
no strict rules on how computers should be hookup, except that any
computer
should be connected to at least two other computers.
Peer-to-peer model is natural and powerful. There is no centralized
controller. When a node
needs to obtain certain information which it doesn't have it asks
its peers, initiating
the recursive traversal of the graph. In the stabilized version
of such network,
by stabilized here we mean the one that has been used for a while,
information is
stored evenly among participating machines.
Regardless of how you decide to organize the network, next question
that you need
to address is how your machines will communicate, what is the protocol.
We live in the world were there are to many different protocols
and platforms;
we are now consciously trying to standardize on just a few. However,
when we speak
about network protocols we need to carefully distinguish layers
of communication
that we mean. Let us use simplified 4-leyer representation of network
communication,
taken from Java Network programming by Elliotte Harold.
The internet layer, IP, defines how bytes should be organized into
packets and the addressing scheme
by which machines on the network find each other. The packets of
data which are send across are
called datagrams. Datagrams have headers which describe the size
its contents, its destination
and origin.
The Transport layer deals with redelivering the data in case if some
of it gets lost. It is also
concerned with order in which packets are received. As most of you
know, two primary
protocols here are TCP and UDP.
Now, in the application layer, you may choose to communicate in
any way you like.
For example, web browsers and web servers communicate via HTTP.
Many financial
applications have their own proprietary message-based communication
formats.
Often we see objects being streamed (serialized) over the network
or methods
being invoked on remote objects.
Java comes with wide variety of facilities for distributed computing
which range from
elementary socket support to Enterprise Java Beans. Today we will
study Sockets
by writing simple chat program. We start by considering most primitive
means of networking in Java - Sockets. In Java, you can think of
a Socket as a
two way data tunnel. This tunnel has input and output streams
Socket is instantiated with network address and port. You send data
by simply writing
to sockets output stream and receive data by reading from sockets
input stream.
The class java.netSocket encapsulates the functionality of client
socket. However, in
order for you to connect to remote host you need to have ServerSocket
on the other end.
The server socket, binds to the port on host where program is running
and blocks
until someone tries to connect to it. As soon as this happens, it
wakes up, negotiates
new port where connection will take place, create new socket to
represent and support
this communication and then blocks again.
The API's of ServerSocket and Socket are quite simple. People who
had to
implement sockets in C would definitely appreciate them.
We now move on to concrete example - chat program.
What does the typical chat program involve?
Well, clients connect to a some defined chat server that allows
them send messages
to each other. The server essentially acts like a proxy, it forwards
a message only
if client for which it destined is logged in. Typical chat program
allows user
to type in message, while receiving messages from other users. This
means that
I/O are running in the separate thread. Writing the chat program
using plain sockets,
even in Java, is not trivial. You will see that there are several
interesting issues and
techniques involved.
Let us first address the communication protocol issues. What is exchanged
between
client and server? We definitely know that it should be more than
just plain messages.
This is where Java serialization together with command design pattern
come handy.
Here is the idea. We construct small command objects which get serialized
and shipped
between client and server. Once command arrives to its destination
it executes
which ever code it needs to execute. This is flexible and powerful,
but requires that
both client and server have all command classes. Here is command
hierarchy:
Commands travel between client and server. Whenever command arrives
on its destination it gets executed with the target object. For
example, here is
the code for login command:
Or here is the message command:
So client and server exchange commands which simply execute API methods
when
they arrive.
Next problem that we want to address is the asynchronous nature of
I/O in chat programs.
Whenever you are communicating with your friend via some chat, you
don't want to
have to wait to type in your sentence while program is receiving
response from your friend.
You want the I/O to be asynchronous - so we have to run them in
separate threads.
Here is the idea. We will create class RemoteDestination, which
will be used both
by server and client, which will encapsulate this functionality.
Here is public interface of RemoteDestination
As we mentioned previously, every remote destination will contain
sender and
receiver which will be running in separate thread. Here is the code:
And here is the rest of remote destination, so that you can see how
these are being used
Okay, now we are all set to write ChatClient and ChatServer. All
that our chat client
should do is just prompt user to login and then let him/her enter
messages.
Finally, we need to do ChatServer. The job of the server is to listen
on a certain port
and wait for connections and messages from clients. Once connection
is attempted,
Server creates an instance of RemoteDestination to represent and
manage this connection.
When Login message from this connection arrives server associates
given user with
this remote destination. Now this user and others can start exchanging
messages.
We conclude with class diagram and link to zip file containing the
code for this chat.