CPSC 329 Software Development Fall 2017

CPSC 329 Lab 9: Client/Server Networking

In this lab, you will be creating a server that provides jokes and riddles.

Objectives

Successful completion of this lab means that you:

Collaboration

Work in pairs (and one group of three) to complete this lab. Only one person needs to carry out the steps in the lab but everyone in the group should make sure they understand what is going on. There is no limit on collaboration with others, but you need to make sure that you understand for yourself how (and why) to do things.

Due Date and Deliverables

due Tue Nov 7 at the start of class

One handin per group.

To hand in the lab, create a handin tag as directed. Make sure the names of your group members are in the commit comment.


Setup

Create a project for this lab:

Provided Code

You have been provided with classes for representing a knock knock joke (KnockKnockJoke) and a riddle (Riddle). Look at the classes to determine how to use them.

You have also been provided with the beginnings of a server (JokeServer) - so far it just initializes the collection of jokes and riddles.


Basic Joke Server

First, create a basic server that tells knock knock jokes. The protocol for a knock knock joke is that the teller of the joke (the server in this case) begins by saying "knock knock". The full joke unfolds as follows:

  server: knock knock
  client: who's there?
  server: [thing]
  client: [thing] who?
  server: [punchline]

Next, create a client to interact with the server:

Since you need to run two programs simultaneously, it is easier to run them from the commandline rather than through Eclipse:

Note that if your classes ended up in a package other than the default package, you will need to add the package name before the class name e.g. java lab9.JokeServer.


Fancier Joke Server

Jokes and Riddles

The server should be able to tell both knock knock jokes and riddles. This requires an expansion of the protocol: the client will first tell the server whether it wants a joke or a riddle.

Repetition and Shutdown

A server that exits after a single client connects is not a very useful server.

Now the server runs indefinitely - it would be nice to be able to shut it down. This can be done by allowing a client to send a "shutdown" message.

What happens if the server is in the middle of telling a joke or riddle when the shutdown command comes? Try it out: open a third terminal window, start the server, run a RiddleClient but don't answer the riddle yet, run a ShutdownClient, then answer the riddle. What happens? Why?


Multithreaded Server

A server that can only handle one client at a time is OK if the clients don't take very long, but in this case a user that is slow to answer a riddle will tie up the server for everyone else. To fix this, the server needs to be able to do multiple things at once - which means it needs threads.

Client Servicing Threads

There will be one thread for each client, plus the main thread which listens for incoming connections. First handle creating and starting the threads:

Shutdown

Shutdown is now problematic because the shutdown command is received by a thread other than the thread running the loop that shutdown should exit. But this can be handled using the polite shutdown pattern:

Try running this - start a server, start a riddle client (but don't give an answer yet), and run the shutdown client. What happens? What happens when you finally give an answer to the riddle? What happens if you start another riddle or knock knock client?

What happens if you start a second riddle client between running the shutdown client and answering the first riddle?

Shutdown should be polite but firm - clients with jokes/riddles in progress should be given a chance to finish, but the server shouldn't have to run indefinitely because a client is stuck in the middle of an exchange.

Try it out - have a couple of riddle clients running when you run a shutdown client, and then wait to see what happens.

Race Conditions

Now that there are multiple threads, are there issues with shared variables, shared objects, or other race conditions that need to be addressed?


If You Have Time

These tasks are optional and won't be graded - try them if you want an extra challenge.

Picking a Joke/Riddle

Also allow the client to pick a particular joke or riddle instead of always getting a random joke/riddle. Modify the protocol so the client sends knockknock n or riddle n as the first line of text, where n is either a number (meaning to tell the nth joke/riddle) or * (to indicate that a random joke/riddle should be chosen).

What if the client sends an illegal joke/riddle number? How will handle that?

Avoiding an Accumulation of Dead Threads

The server adds each new client thread to a collection so that it can give each client a chance to finish when it shuts down - but most clients will finish long before then, and in a long-running server, storing all those completed Thread objects can take up a lot of space.

One option is for the server to periodically go through the collection of threads and remove ones that are no longer alive.

Another is for a ClientServicing thread to remove itself from the collection when it completes. Implement this option. Keep in mind the need for mutual exclusion since the main thread adds to the collection and client threads remove.

User Submission of Jokes/Riddles

Allow the user to submit new jokes and riddles. This will require modifying the protocol to accommodate the new action(s) as well as properly handling mutual exclusion conditions.


Handin


Valid HTML 4.01!