Continue working with your design from
Studio 7 to
You can get a C on this lab for code that works, but better grades are
available only for clean designs! Take note of everything below, ask questions,
and work toward code that is simple and clean.
Your design must include the following classes, all in the flap
package, with constructors as follows:
- From server to client:
- one constructor: represents the signon frame as if it were sent to client from server.
This class should probably extend ServerFrame.
- Such constructors
are handy for testing, because they doesn't really read any input to obtain
- What other methods should ServerSignonFrame have, based on the
contents of such frames?
- ServerSignonFrame(DataInput din)
- another constructor: represents the signon frame actually trasnmitted from
client from server.
- This class should extend ServerFrame.
- It takes an implementation of DataInput as its parameter.
- The DataInput is provided so that ServerSignonFrame can
read its fields from the server.
- Go ahead and complete the constructor assuming you have the DataInput
object at hand. We can worry about that connection later.
- ServerDataFrame(String s)
- constructor: represents a data frame as if it were received from the server
and contained the String s (useful for testing).
This class should extend ServerFrame.
- ServerDataFrame(byte in)
- constructor: represents a data frame actually received from the server.
The server provided the array of bytes in, and a String needs
to be constructed from that. See
- This class's primary responsibility is to provide the method
- You are given an InputStream, but if you want to deal with
richer types on input, use the I/O decorations to create richer streams
for yourself. For example,
DataInputStream provides methods to read
2- and 4-byte integers.
- The ServerFrame readFrame() method deserves some thought.
It has to read enough of the message to know what kind of frame to create.
Once the proper frame is known, it can be constructed and the payload can
then be processed to
populate its own fields. The constructors above
provision for that by accepting suitable inputs.
- One problem here is how to get FLAPInputStream's readFrame()
to provide a DataInput to ServerSignonFrame.
You want to give the constructor a DataInput to process the current
frame only! Don't just hand over the socket's input stream, because if the constructor
reads too far, or not far enough, the reamining input will not be processed correctly
and such errors are hard to find.
- A handy class to help with that is ByteArrayInputStream.
That class will take an array of bytes (such as the payload of the message)
and provide a normal input strream using
only those bytes.
- Think about how to use decoration to make a DataInputStream out
- From client to server:
- ClientSignonFrame(String username)
- constructor: represents the version of a signon frame sent from the client to
This class should extend ClientFrame.
- ClientDataFrame(String s)
- constructor: makes a frame for sending from client to server.
This class should extend ClientFrame.
- This class's primary responsibility is to provide
the method void writeFrame(ClientFrame f). The following statements
are meant to guide your thinking so as to create the simplest implementation of
this part of the flap package:
- Every framed message from the client to the server has the same format in terms
of the asterisk and the sequence number. Such code should appear in only one place.
- The frame type does differ by frame. How do you ensure that a sutiable method to get
the frame's type is available for all extensions of ClientFrame even though
such an implementation is not possible in ClientFrame itself?
- The framed message requires a payload and its length must be known before the
payload is sent.
- The safest approach would require extensions of ClientFrame to provide
the contents of the payload, so that the calculation of its length occurs in just
one spot. How is such a method provisioned for the extensions even though
ClientFrame itself does not know how to produce a payload?
The ClientSignonFrame and ClientDataFrame classes just
need some kind of output stream to create their payload. The method provisioned
could pass such an object.
- The ByteArrayOutputStream would be a good place
to look for methods that help you achieve these goals. It allows an output
stream to be built without actually sending bytes over the socket. Once all the
writing is done, you can get the bytes that would have been sent, know their length,
and then send the appropriate data to the server.
One challenge in sending and receiving data is effecting the proper data format
outbound and inbound. Below are some examples.
- If you want to send a single character, such as the letter a, the
easiest way is to simply write('a'), which transmits the ASCII
value for a as a single byte across the socket.
A common mistake is to use writeChar. It sends a character as two bytes
which will throw the protocol off if it expects one byte.
- If you want to send an integer value v, such as 5, you must
send it in the number of bytes that are expected. This was discussed in class,
but for reference you may want to examine the following:
- To send the integer as a single byte, you can simply write(v).
Although the type of the parameter is int,
only a single byte is transmitted.
- To send the integer as two bytes, consider how a short
value is transmitted using
- To send the value as four bytes, consider how an int value
is fully transmitted using
When you are ready, show your work to the TA and get checked off for this lab.
Thanks to Matt Gokel for providing the following:
Last modified 08:59:23 CDT 03 June 2010
by Ron K. Cytron