Assignment 3 -- 60 points

Due: Wednesday, October 22.

Summary: Implement two programs: a socket-based client and server. The client will send both regular and out of band (OOB) data which is entered by the user, and the server will print out the data it receives (and will specify if the data is OOB).

Client Detail: The client (called "client.c") will connect to a server on a certain machine and port, as specified on the command line. The machine can be referenced by name, so you will have to call gethostbyname() to get the IP address for the connect().

Once connected, the client will print a "client>" prompt, then read lines from stdin which it will send() to the server. The newline character (if read) should not be sent, nor should the null-terminator! Additionally, if the first character of the entered line is an exclamation point ('!'), then the next character should be sent as OOB data. Only one byte of OOB data can be sent at once. Do not send the '!' with the rest of the data!

The client should print the number of bytes actually transmitted to the server.

Once the client reaches EOF on stdin (i.e. "^D" is pressed), it should close() the socket and exit.

Sample run:

    $ client
    usage: client host port   [Print a usage message!]
    $ client guzzler 3490
    client: connecting to 132.241.4.12, port 3490
    client> foobar            [Sends "foobar" normally]
    client: 6 bytes sent
    client> !b                [Sends "b" as OOB data!]
    client: 1 bytes OOB data sent
    client> ^D
    $ _

Server Detail: The server ("server.c") will listen on a specified port for incoming connections. Once it gets a connection, it will recv() data and print it out. (You do not need to handle multiple connections simultaneously.)

If the server receives OOB data, it will have SIGURG raised so it can handle the OOB data. You will need to implement a signal handler to deal with this data.

The server will take a single argument on the command line: the port number to listen on.

Sample run:

    $ server
    usage: server port
    $ server 3490
    server: listening on port 3490
    server: waiting for a connection...   [this is where it accept()s]
    server: got a connection from 132.241.4.10
    server: read 6 bytes, "foobar"
    server: read 1 bytes OOB data, "b"    [inside the SIGURG handler]
    server: remote side closed connection
    server: waiting for a connection...   [wait for another one]

Hints: The server should contain the following fcntl() call after the accept() (be sure to include <unistd.h> and <fcntl.h>):

    newfd = accept([...]);
    fcntl(newfd, F_SETOWN, getpid());  /* returns -1 on error!  check it! */

This causes the server to receive SIGURG when OOB data arrives on the newly accept()ed socket.

Use the MSG_OOB flag with send() and recv() to handle your OOB data.

Don't hit ^C to break out of your server while the client is still running. If you do, the next time you try to run the server, you will get an error from bind(): "Address already in use". If this happens, just wait around a bit--it'll return to normal in a few minutes.

Of course, it could be that someone else has stolen your port. I suggest you choose your own port number (instead of 3490) or all of you will clash together trying to use the same port. Remember: you can have any port between 1024 and 65535.

Null-terminate your strings after you recv() them! (Printing a non-null-terminated string will lead to problems.)

If you send "!12345" from the client, what does the server receive? Notice that only the "5" arrives as OOB data. This is OK.

Directory structure: Please place the sources for this program in your "~/298C-02/prog3" directory. Be sure to set the permissions so we can read the program when it's due.

The Makefile: Implement a Makefile for this project. We should be able to simply type "make" and to build the client and server.

Late Policy: 6 (six) points per day, as the clock rolls over midnight.