Program 3


This program will extend your repetoire of network programming calls slightly, but is primarily an example of a problem that fits the client-server pardigm and requires that you design the logic.

The other thing that you should do with this problem is set up the client and server to more flexible by using a well-known port and for the client to be able to accept a machine name as a parameter. For example, starting the client and server should occur like this:

Note, you don't have to use the names client and server.

cs440-00 through cs440-07 are ports that have been set up on on the machines in EPS 254 just for use by this class. Since they have the same port numbers assigned, using them guarantees that a client and server will be able to communicate as long as they choose the same port. By handling things this way, you can have your client and server change ports if one is busy. The use of a machine name means that your server can run on any machine, and you can match the client at run time. The conversion of the port and machine name to port numbers and addresses is described in the Unix Network Programming Manual on the CS440 -> Laboratories -> Resources page (Getting Host Data and Getting Service Data).



As part of this program, create routines for clients and servers to use to open ports in a uniform manner. For the client, the prototype should be of the form:



where server_name is the DNS name of the node, service_name is the name of the port in /etc/services, and socket_type is either SOCK_STREAM or SOCK_DGRAM (it could be an enum type instead of an int). The routine will return a socket which has been connected to the server unless some error occurs.

The server routine would have a similar syntax, such as:



and it would return a bound socket. This routine should not do a listen or an accept. Note that in most instances, the parameter server_name will be NULL, which indicates INADDR_ANY, but not always. The server can open a socket that can only be connected to by a specific host if it wants to.

You don't have to use these names or calling sequences if you prefer others, but you must build routines to do these mundane tasks. You really should build a library that can be easily linked with any program. That can be done by compiling the files that contain the source into .o files and then using:



to build the library. When linking, the cc argument "-lmynetstuff" will link the libarary to your other code.

You should also design utilities when you need them. For example, routines that will print the dotted-decimal notation from an int or convert from IP address to DNS name or vice-versa.



Finally, down to the program itself. You are to build a server to return random numbers to the client. The clients sends a request of the form:

where RN is simply the request code, and nnn-nnn is two numbers separated by a dash indicating the low and high of the desired range. They don't have to be three digit numbers. For example,

asks for a random number between 10 and 20 inclusive (it could be 10 or 20).

To find out how to get random numbers, take a look at the random number howto.

The server responds with a message of the form:

Where xx is simply a message indicator and nnn is the random number (not necessarily three digits). x is N if the random number is present and E if there is an error and nnn will be the error code; 1 if the received message was in error and 2 if the server was unable to generate a random number.

This seems like a pretty trivial problem, but the networking issues can be tricky. First, the server and client may be running on machines with different storage formats (Big Endian vs. Little Endian), so you have to insure that all numeric values are transmitted in a common format. This is typically network byte order, which on the Internet means Big Endian. The routines to handle this conversion are htons, htonl, ntohs and ntohl (and there are others).

Turn in your client and server code and examples of runs showing that you can exchange messages.