CSE 461 Autumn 2006
Homework 6: Socket Programming

Out: Friday December 1
Due: End of (midnight) Friday December 8

Due to popular demand, an extra credit extension has been added to this assignment. Points are small. Life is fleeting.

Overview / Goal

The goal of this assignment is to make sure you have experience writing simple programs using sockets. There are two independent pieces: a client program, which can be used to talk to existing servers (e.g., web servers), and a server program that can talk to existing clients (in particular, telnet). Your client implements, roughly, the functionality of telnet. Your server implements the echo service. While you can use your client to talk to your service, the two are really independent, so you can build and debug one entirely before starting on the second.

The Client Progam: telnet

The actual telnet is a program (and a protocol) used to establish connections to remote machines. It's the old, insecure version of what we now use ssh for. At the heart of telnet is establishing a TCP connection with a remote port. That's the only part we're implementing; anything you might read about the telnet protocol is a complication beyond what this assignment is asking for.

Your client should be invoked something like this:

$ java telnet www.cs.washington.edu 80
It's first argument is a host name, and its second a port number. It tries to open a TCP connection to that host/port. If it succeeds, it then sends whatever is typed to the destination. It also concurrently prints whatever is sent from the destination. That's pretty much everything. (Note that the server may not send anything back in response to an input line, or may send something even before the user has typed anything.)

There are two design complications you have to face, but we don't care what you do about them. The first is how the user terminates your program. One possibility is that there is some special character (or character sequence) that acts as a quit command, e.g., ctrl-D. The upside of that approach is that this it's pretty clean. The downside is that the user has no way to send whatever your command is to the other end. A less clean, but possibly easier to implement, solution is to require the user to ctrl-C to get out of your program. (Technically, the second option is a special case of the first, I suppose.)

The second (and similar, in nature) complication is what to do about normal line editing. For example, if the person using your client program types tesin<backspace><backspace>ting, should you send to the server the seven characters testing or should you send the eleven characters actually typed? Does it send each character as it is typed, or only when the user types a newline? Do you send the newline? Again, you can decide whichever seems right to you.

To test your client, you can connect as in the command above, and then type these three lines (the last one being an empty line):

GET /index.html HTTP/1.1
Host: www.cs.washington.edu

That's an HTTP request asking for what you normally think of as http://www.cs.washington.edu/index.html. If your client is working, a lot of text will come be printed.

The Server Program: echo

Your server opens a TCP socket and waits for clients to connect to it. It should be invocable in two ways that look a lot like this:
$ java echo 2345
$ java echo
In the first form, the user is indicating what port it wants the server to listen on. In the second, the server is asked to just use an ephemeral port. (When invoked this second way, the server should print out the port number it is listening on.)

The server waits for client connections. When one is established, it simply reads whatever is sent to it and sends it back. This means that if you connect to your server using the actual telnet utility (or your own) you should see whatever you typed repeated.

One feature not to overlook is that more than one client can connect to a single echo server at a time, and each client's input should be echoed back promptly.

Programming

There are two somewhat challenging pieces to building both the client and the server. First, you have to figure out what the correct set of socket calls is for each case.

Second, notice that both programs need to be doing more than one thing at a time: the client needs to be both reading from the keyboard, so it can send that data to the other end, and reading from the socket, so it can be printing. The server needs to be able to converse with multiple clients at a time. There are various implementation approaches that let you do this, but I think by far the easiest one is to use multiple threads. For the client program, one thread sits in a loop reading the keyboard and writing the socket, and another just the opposite. For the server program, there is a thread per active client, each sitting in a loop reading the socket and then writing the socket.

These programs are not long. My client is 56 lines of Java (including blank lines and my usual over abundance of comments). The server is 47 lines. Nonetheless, they can be frustrating, because there are probably a lot of new details to work out: how/when to start/stop threads; how to read from a socket; how to write to a socket; etc.

You can implement in either Java or C/C++. (Other language choices are possible by prior approval.) If I were you, I'd choose whichever I was most comfortable with, remembering that I had to use threads. I wrote sample solutions in Java, and since I don't know Java very well I spent most of the hour it took me to do this assignment trying to figure out lines like this one:

BufferedReader in = new BufferedReader( new InputStreamReader(System.in) );
I admit it's pretty frustrating to have to spend time sorting through documentation to figure out how to say the thing you know perfectly well you want to say. The narrow goal of this assignment is to gain experience programming with sockets, though, and this is unfortunately part of it.

Teams

Nope.

Deliverables

turnin your code files (I expect there will be two, but the number is up to you), plus a file named README.txt. In the README explain:

Obtainables

These functions are so standard that it's got to be easy to find full program solutions sitting around on the web. Finding them, copying them, and turning them in isn't useful to anyone. Remember that the point of this assignment is not that we need 55 working copies of telnet and echo, it's entirely the experience of having built them. You'll know if you're having an appropriate experience, or if you aren't, so that should be the standard you apply in deciding what you're "allowed" to use and what you aren't.

Legitimate Obtainables

Grading

We'll look at the README file and at the code. We might build the code. We might run the code. We might compare the code with a vast inventory of sample programs we've collected from web searches. We might compare the code with other code turned in for this assignment.

Planning

This assignment is intended to be small-ish. If you have programmed with sockets before, the odds are you'll find it trivial. But, I don't expect you've programmed with sockets before, and I expect that you don't have much experience with threads. Summing all that up, I'm guessing that most people will need between 2 and 10 hours to complete this work. I think a few people will need a lot more (that's just statistics - I'm not thinking of anyone in particular). As usual, it would be wise to try to find your 2 to 10 hours earlier than later.