Assignment # 8
Playing Network Ping Pong
Due: Friday, December 4th by midnight.
Deliverables: Email all files that you create to cis3931@cs.fsu.edu
by the due date, including a journal/diary of the steps you
went through during this assignment. Since many of the assignments
involve writing Java applets it will greatly assist the grading of
the assignments if you create HTML on your home page that includes
the assignment's applets. Please include the web address of your
applet in the journal/diary. Note that for assignments that require
you to create source code yourself rather than type in existing code
(like this one) you should take careful measures not to
accidentally make your .java files world-readable within your HTML
directory.
When emailing your files it can be problematic to faithfully
re-create the file names. Here are detailed instructions that you can
use for this and future assignments. If you use xi.cs.fsu.edu
(which is running Solaris) you can create a single compress "tar"
file that can then be emailed to cis3931@cs.fsu.edu.
cd location_of_P8_source
gnutar czvf ~/P8.tar.gz .
If you use an email client that supports attachments then you can
just attach the file P8.tar.gz to your email submission. If
you do not use an email client that supports attachments you will
first have to convert the binary compressed "tar" file into a format
suitable for an email message, such as uuencoding. Here is an example
of encoding the P8.tar.gz file and sending it via a UNIX pipe
to a mail client:
uuencode P8.tar.gz < P8.tar.gz | /usr/ucb/mail -s "P8.tar.gz" cis3931@cs.fsu.edu
If you choose to use some other operating system, such as Windows
'95, Windows NT or Windows '98 be careful that you use a compression
agent that correctly preserves both case sensitivity and the entire
file name length, such as WinZip.
You will be asked to re-submit your assignment via email if the
format you use is not correctly identified and/or formatted. Please
do not email all the files separately.
Assignment:
This lesson uses the material in Lesson
24 (All About Sockets). Specifically, you are to write a Java
network client applet (pongClient) and a Java network server
application (pongServer). When completed, your program, along
with a masterServer and other student's solutions, will
interact in an exciting fashion. To understand what is required a
discussion of the protocols needed for client to server and server to
master server is presented, followed by specific requirements for the
client and server.
The Pong protocol was developed to allow you to interrogate a
number of servers from a single client. It will be used by your
pongClient to measure how long it takes to contact a list of Pong
servers. One of the applet security manager rules enforced within
typical browsers is that a network connection between an applet can
only be made back to the host machine that served up the web pages
containing the applet. For this reason you must develop a Pong server
that runs as a standalone Java application on the same machine as the
web server. Your Pong server will act as an intermediary, performing
as a relay agent for the Pong protocol.
You are provided a Java file containing all of the definitions you
will need for the following protocols (you can find it here, in
Pong.java). It is important that
you use these values, otherwise your client and server will not
properly interact with the other Pong servers and the master Pong
server. In addition to the public constants, you need to use the
pongIdentity class to correctly
identify your pongServer to the masterServer. All communication
between clients and servers is through the Socket and ServerSocket
class. All data sent through the sockets is serialized.
pongClient to pongServer Protocol
pongClient request
|
pongServer response
|
Pong.CLIENT_LIST
|
If OK, Hashtable
of pongIdentitys, else Pong.CLIENT_NAK
|
Pong.SERVER_PING, pongIdentity of server to ping
|
IF OK, Pong.CLIENT_ACK, else Pong.CLIENT_NAK
|
pongServer to masterServer Protocol
pongServer request
|
masterServer response
|
Pong.SERVER_LOGIN, pongIdentity of this pongServer
|
If successful, Pong.SERVER_ACK, else
Pong.SERVER_ALREADY_LOGGED_IN
|
Pong.SERVER_LOGOUT, pongIdentity of this pongServer
|
If successful, Pong.SERVER_ACK, else
Pong.SERVER_NOT_LOGGED_IN
|
Pong.SERVER_LIST, pongIdentity of this pongServer
|
If successful, Hashtable
of pongIdentitys of all logged-in pongServers, else
Pong.SERVER_NAK
|
Pong.CLIENT_PING, pongIdentity of this pongServer
|
If successful, Pong.CLIENT_ACK, else Pong.CLIENT_NAK
|
Pong.SERVER_PING, pongIdentity of pongServer to ping
|
If successful, Pong.CLIENT_ACK, else Pong.CLIENT_NAK
|
To see the protocol in action, look at the pongClient
applet. It will help to see how it runs before trying to figure out
how the pongClient and pongServer are supposed to work.
pongClient Specification
- Create a Java applet that uses the 1.1 event model. You can
model it after the P6 solution as well as the network client on
page 919 (the Knock Knock client).
- Create a start Button, a TextField to accept the pong server
name, a TextField to accept the pong server port address, an
extended Canvas to draw the Ping Circle and a non-editable
TextArea to display the log of events.
- When the start Button is pressed, take the input from the
server name and port fields and initiate a connection to that
pongServer:
- Create a Socket connection to the server name & port.
Log the success/failure of the connection in the log
TextArea.
- Use Pong.CLIENT_LIST to get a Hashtable
of pongIdentitys for each of the other pongServers that are
running.
- Walk through the hash table, issuing a Pong.SERVER_PING for
each pongIdentity, logging the progress of the ping in the
TextArea. Send the pongIdentity of the pongServer with each
SERVER_PING.
- Keep track of the number of milliseconds it takes for each
Pong.SERVER_PING (you may find a Vector
useful, as well as System.currentTimeMillis()),
as well as the minimum and maximum milliseconds for any one
ping.
- Plot the ping time in a unit circle, using the circle
origin as time zero and the line segment length as a ratio of
the millisecond time. Notice that you will need the maximum
ping time to correctly scale your lines. Spread the lines
evenly around the unit circle (two lines would be 180 degrees
apart, three lines would be 120, etc.). Print the clientName of
the server at the end of the line.
- If while contacting a pongServer you are unable to receive
a Pong.CLIENT_ACK, report that the host is "dead" in the log
window and discard the timing for that server (don't draw it's
line, since it was never ping'ed).
- Your paint() method must be capable of redrawing the last Ping
Circle whenever it is called, rather than just when the data is
initially created. Use a Canvas preferred size of 300 by 300.
pongServer Specification
- Create a multi-threaded network server Java application. It
must accept two command-line arguments: the name of the server and
the port number that this server will listen on. A good starting
point for figuring out the structure of the program can be found
on page 920 (the Knock Knock Joke Multiclient Server).
- Open a Socket to the masterServer (it is listening on host
Pong.MASTERHOST, port Pong.MASTERPORT).
- Create a pongIdentity and fill out the fields with the correct
values (clientName, myIP and myPort).
- Send the masterServer a Pong.SERVER_LOGIN, followed by your
pongIdentity. If you do not get back a Pong.SERVER_ACK, print out
an error message and exit.
- Create an idle time monitoring thread that will be used to
kill your pongServer whenever enough time has elapsed without
receiving any requests from a client. Use Pong.MAX_IDLE_TIME (the
value is in seconds -- it's set to 5 minutes) as your maximum idle
time. Your idle thread will sleep at some reasonable time interval
(wake up once very 5 seconds) and then determine if more than
Pong.MAX_IDLE_TIME seconds have elapsed between the last accept()
call from the server's main loop and now. If so, your idle thread
will shut down your pongServer.
- Create a ServerSocket and use accept() to listen for a client
request. If a request comes in, spawn a thread to handle that
client's request:
- If Pong.CLIENT_LIST received, send a
Pong.SERVER_LIST to the masterServer along with your
pongIdentity. You will receive back a Hashtable
of all the pongIdentitys known by the masterServer or you will
receive one of the error values (Pong.SERVER_NAK, etc.). Return
to the client a Pong.CLIENT_NAK if you receive an error, else
pass the Hashtable back to the client.
- If Pong.CLIENT_PING received, send a Pong.CLIENT_ACK
back to the client.
- If Pong.SERVER_PING received, read in the pongIdentity
of the pongServer to ping. Open a Socket to that pongServer's
name and port (retrieved from the pongIdentity) and issue a
Pong.CLIENT_PING. If a Pong.CLIENT_ACK is received, send back a
Pong.CLIENT_ACK to the client, else send a
Pong.CLIENT_NAK.
- Continue reading client requests within this thread until
either an invalid request is sent or your server's idle timer
expires.
- Note that the masterServer will remove any pongServers from
it's internal list one hour from the last received
masterServer request. You will either have to stop and restart
your server manually or attempt to Pong.SERVER_LOGIN again.
Notes
- You must select a pongServer name and a port number that are
unique. As a suggestion, your server name can be simply your first
and last name. If you prefer anonymity, select a catchy pseudonym.
As for the port numbers, you must select one that is unused on the
machine that you choose to run your server on (more than likely
you'll choose xi.cs.fsu.edu, since that's where the departmental
web server runs). You can use a number unique to you that is any
unused random number between 1024 and 65535 (I suggest you don't
use any private numbers, such as a part of your SSN or a
credit card :). You don't have to tell anybody else your number,
as it is passed to all other pongServers via the protocol.
- Note that the Computer Science firewall machinery will ONLY
let "officially-blessed" Socket traffic into and out of the
department (email, FTP, web traffic, etc.). This means you cannot
run your server on a machine outside of the department and expect
it to work. Proxy solutions are available, but complex.
- MAKE SURE you write your server so that it does NOT
get into any tight CPU loops or hangs around idle for more
than 5 minutes. If your server abuses the system, it will be
killed by members of the System group and noted for future use by
the grader. If written correctly your server will have minimal
impact on the system.