The exchanger

Client

Clients using the exchanger send a message of the following format:

SWAP stuff USING key

This should result in a response of the form:

RETURN stuff USING key

The stuff and key are any words consisting of characters that aren’t white space.

If a message is sent that isn’t in the proper format, the response should be an exclamation point followed by the original message. For example, if the following message is sent.

!This is a very, very bad message!

This should be the response:

!!This is a very, very bad message!

We will follow the convention of having lines terminated by CRLF, or '\r\n', in line-oriented networking protocols, such as HTTP. Unfortunately, it can be a little difficult to generate a real CRLF in some programming language and platforms.

To avoid this program, try using the following two routines when you are using Python.

def getNetLine(netinstr):
    try:
        inline = netinstr.readline()         # up to \n or EOF
        if (inline[-2:] == '\r\n'):          # CR LF -- usual case
            return inline[:-2]
        if (inline[-1:] == '\n'):            # LF -- being tolerant
            return inline[:-1]
        return ''                            # closed connection
    except:
        raise

def putNetLine(netoutstr, line):
    try:
        netoutstr.write(line + '\r\n')
        netoutstr.flush()
    except:
        raise

Server

Ultimately, the server will allow pairs of clients to swap stuff, but we are going to proceed in small steps.

Step 1 — Homework 2

Write a server the reads lines from a client and echoes with SWAP replaced with RETURN. Your client should run on TCP port 33101 and needs to accept only one client at a time.

Step 2 — Homework 3

Modify your server so that it could accept several clients simultaneously. In Python, you’ll need to use either the difficult threading or the dreaded select interface to do this.

Step 3 — Homework 6 — Repeater

The repeater is a hardened version of the Step 2 solution. It parses good messages and returns an appropriate response. It returns a bad messages with the prefixed exclamation point.

There is a repeater running at port 33101 of hazelwood.cs.unca.edu which you can access using the following command from a Linux system.

nc -C hazelwood.cs.unca.edu 33101

Try the following command on any computer supporting telnet. Most Windows platforms do have telnet installed.

telnet hazelwood.cs.unca.edu 33101

Step 4 — Homework 8 — Initializer

The initializer server remembers the first stuff associated with a given key and always returns the same stuff for that key.

For example, suppose there is an initializer running on hazelwood.cs.unca.edu . If you connect to it and send the following line:

  swap csci  using  bestdepartment

If this is the first time a swap has been attempted with the key bestdepartment, the response will be similar to the following:

RETURN csci USING bestdepartment

All subsequent attempts to swap with the key bestdepartment will yield the same response.

There is an initializer running on joe.cs.unca.edu at port 33101.

It is certainly possible for you to write a server that works 99.44% of the time without using a Lock object from the threading interface. However, good solutions must provide some way of dealing with races that could occur when two client connects try to set the same key and the same time.

Step 5 — Homework 9 — Exchanger

The exchanger server pairs up two clients which wish to exchange stuff for a particular key.

For example, suppose one client connects and sends the following line:

  swap  Nanci  using  singer

This client will be blocked, unless there is already another client waiting with the key singer,

Now suppose a second client connects and sends the following line:

  swap Iris  using  singer

Now both clients will be unblocked and will swap their stuff. The first client will receive the message:

REPLACE Iris USING singer

The second client receives the message:

REPLACE Nanci USING singer

You’ll need to use Condition and Lock objects from the threading interface on this one.

There is an exchanger running on emma.cs.unca.edu at port 33101.

How much code?

My servers are written in Python.

The definitions of getNetLine and putNetLine are stored in a file where they can be included from other Python programs. This file contains 17 lines.

My repeater server is 84 lines of Python code. 7 of these lines are blank. 2 lines are used to call the main routine. The main routine creates the server socket, accept new connections, and creates a thread to handle each connecion. The main routine is 26 lines long. About 6 of those lines are used to “reap” threads of inactive connections. I don’t expect most solutions to deal with this.

There is a class handleClient for handling connections. This class extends threading.Thread and is 33 lines wrong. About one-third of those lines are boring Python, such as
        self.addr = addr
There is also an 8-line Python module for reaping inactive threads. The remaining lines are import statements and a recursive expression “compile.”

The initializer and repeater servers are very similar. The handleClient class has a single change: a call to a 10 line function handleExchange which “remembers” the first input for a key. handleExchange uses Python dictionaries to map keys to value and locks for synchronization.

The only differences between the exchanger and initializer servers are found in the handleExchange routine. The exchanger’s handleExchange is 18 lines long and uses Python condition variables to make the connection rendez-vous.