Program 2


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: 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 be 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.


Finally, down to the program itself. You are to build a simple database lookup program. On the server side, you will have a file of the following form:



The client will query the user for a name and send a request to the server. The server will search this file for a given name and return the hourly wage and hours worked to the client. The client will output the name and the total pay (hourly wage times the hours worked). This is an incredibly simple DB problem, but the networking problems are not so simple.

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).

Unfortunately, because floating point values vary in storage scheme, there is no network byte order for them, so you have to invent your own. In this case, what you should use is the following: The handling of floating point numbers is often done this way. If you have the value 16.45, the frexpf function will convert it into a floating point mantissa and characteristic (which would be 0.1645 and 2 in base 10, although frexp provides the characteristic in base 2). Then, you can right shift the decimal point for the mantissa 31 places to get an integer. On the receiving end, scalbf can be used to reverse the frexp process.

Since the server might detect an error in the search process, it also needs to be able to return an error. This can be accomplished by adding a state value to the return message, so that the format looks like this.

The data for the database is here . Test your program for the following cases and turn in the source and the test runs. Don't worry about error checking on the input. Assume it either matches the name exactly, or the search fails.