This week's laboratory explores the basics of networked communication.
In addition, threading and the listener model play significant roles.
Finally, this lab provides an opportunity for you to return to some of
your previous code. In this lab, you will implement a networked
version of your breakout game from laboratory 5.
In order to complete this lab, you will need to be familiar with
several ideas that we have covered in recent weeks. This prelab
reviews many of those concepts. You should bring to lab written
answers to each of the questions marked with a Q in this prelab
By now, you should be familiar with the Button
relationship. In a similar fashion, the breakout code has a World <->
relationship: Changes made in the World result in WorldEvent's
being sent to registered listeners.
Q: Using the javadoc linked above, answer the following
questions (in writing for your prelab):
- What methods must a
- What information does a WorldEvent
- What interface does WorldEvent implement?
- If ears is a WorldListener and globe is a World, how would
you set up ears to listen for changes to globe?
You will also need to understand how to use the cs101.net.Wire
interface and its implementing classes cs101.net.ServerWire
You will be creating your Wires in a slightly different way from what we did
Q: Look carefully at the two Wire classes. A Wire can
be built in several ways. Write a short piece of code that uses
one of the cs101 Wire classes (which one?) to send the string
"hello" to host 10.40.27.4 on port 4321
without ever prompting the user for the host and port. (This
code won't actually run because nothing's running on 10.40.27.4 to
receive your string)
- cs101.net.Wires are actually hiding java.io.ObjectOutputStreams. What are the requirements on Objects that may be sent
(and thus read) by ObjectOutputStream?
- What objects do you know
satisfy this property? Any in breakout?
Finally, read through the lab assignment below and come to lab
ready to build your lab OR full of questions about what you don't
understand. Also, please be sure to bring your written check-in
questions (answers to everything marked with a Q above) and
your working breakout code from that previous lab.
We're going to invent the game of networked breakout. The game will
be a cooperative venture between players to demolish all the bricks.
To accomplish this, we'll start with 2 working single-player breakout
games and connect them so that they can share balls. To simplify the
network interaction, all bricks on "the other side" will be rendered
as a default "Unknown" brick and the balls will only be rendered when
they are on "your side". The local ("your") board is located on the
bottom and the remote ("the other side") board is upside-down.
Below are a pair of screen shots showing actual gameplay.
Note the ball crossover occuring.
The target exercise is to have a working net breakout game.
- Get network settings
First, you will need to change the way that you start your breakout
game. Last time, you started the program off with a main method that
simply creates a GameFrame using that class's no-args constructor.
Now, you will have to use a different constructor that takes a
NetworkSettings object. (Don't worry, Ben's built the NetworkSettings
for you. You just need to use it.)
You'll want to look at the javadoc for NetworkSettings
so you understand how to get the user's selection out of it.
Now, instead of constructing your GameFrame in
main using the no argument constructor, build an instance of
NetworkSettings, getSettings() it to get the settings from the user,
and pass this object to the GameFrame constructor.
- Create a StudentConnector
Unfortunately, you can't compile and run your code yet. The GameFrame constructor will attempt to create a
breakout.StudentConnector object, and you haven't written this yet. A StudentConnector must implement
and have a constructor with the following signature:
public StudentConnector(World local, World remote,
NetworkSettings settings) Write something that just barely
compiles. (What methods?) Test it and let us know that you've gotten
Instead of jumping directly into the network bits, let's first arrange
to find out what's happening in the game. Update your
StudentConnector to implement WorldListener and have it register
itself as a listener on the "local" world during StudentConnector's
constructor. This way it'll find out when the player loads a board,
breaks bricks, or has a ball leave the board. Have your code print
out something when these events occur. Test it.
- Wiring up
Implement a connect() method for StudentConnector. Based on the
NetworkSettings passed to the constructor, build an appropriate Wire
with the correct parameters. isConnected should return true
if the connection succeeds.
- Sending events
Update the WorldListener methods to send along the event data over the
Wire. Remember only to attempt to send if you're connected. Failures
in sending should signal that you aren't actually connected. These
methods should be very simple (solutions are ~6 lines long each).
- Receiving events
When the connect button on the GameFrame is clicked, your
StudentConnector's connect() is called. Your
connect() method should attempt to connect with the given
network settings. It should create a new Thread to read incoming
events from the network. One way to accomplish this is to have
StudentConnector also implement Runnable. Implement a read-loop that
just prints out the events it receives. Start up the read-loop when
you've successfuly connected. Any communication failure means that
you aren't really connected. Together with your code from the
previous task, you should be able to test and see if the two programs
- Doing the Right Thing
Now, think about handling different events in different ways.
- ADD_BRICK events from the network should result adding an
to the remote world.
- REMOVE_BRICK events should result in removing a brick at
the given location.
- BALL_TRANSFER events should cause a new SimpleBall to
be added to the local world (use this constructor). The supplied direction is
incorrect (it's pointing in the wrong Y direction), and the position
needs to be mirrored on the X axis, and slightly offset from the top
of the board (so as to avoid it immediately crossing back over).
However, just adding these will result in concurrency
problems! The network thread handling the above events can
interfere with the object and rendering threads of the game. In order
to avoid this problem, the locking discipline for Breakout is
to acquire a lock on a World before interacting with it. In plain
terms, your code must enter a synchronized (World)
block before calling any methods on the World. The
synchronized block waits until it acquires a lock on the
given object before proceeding. Which world you synchronize on
(local or remote) depends on which one you are
working with at the time.
Do NOT synchronize outside your while (true) loop
or have the synchronized block include reading from the network! The
board won't display while the network code holds the lock on a World!
As extra gravy, try implementing the networking pieces without using
If you are still looking for more, you can always network your
Scribbles (according to the Shared Whiteboard
assignment on the cs101 site).
Your completed assignment should include:
- on the front page, how much out-of-class time (approximately)
you've spent on reading, on preparation of the homework, in lab, and
on other non-class-time course-related activities (and what).
These times should include work from last Wednesday 5pm to this
Wednesday at 5pm
- your code and a description of its functionality.
- documentation of your code. (This can be inside the code.)
- your observations concerning
- a brief description of the check-out interaction, and answers
to any specific issues s/he may have asked you to address.
- the names and roles of any collaborators in any parts of the
- a brief status update on how your final project is
- the coolest thing you've heard this week (not necessarily pi-related)
Lab assignments are due on Wednesdays at 5pm. They may, of course,
be turned in earlier.