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
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
'\r\n', in line-oriented networking protocols,
such as HTTP.
Unfortunately, it can be a little difficult to generate
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
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
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
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
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
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
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.
handleClient class has a single change:
a call to a 10 line function
which “remembers” the first input for a key.
handleExchange uses Python
dictionaries to map keys to value and
The only differences between the exchanger and initializer
servers are found in the
handleExchange is 18
lines long and uses Python
condition variables to make the connection rendez-vous.