Assignment 4 step-by-step guide
Steps
-
Read up on RPC in the lecture notes.
-
Go through the RPC programming tutorial. Pay attention to the completely rewritten makefile in step 6. You can use this as a basis for the makefile for this assignment (there's a link on the page for downloading the makefile). Optionally, you can also get the demo,
rpcdemo.tar. Extract it with:tar xvf rpcdemo.tarThen change directories:
cd rpcdemo/step-by-stepYou will see several directories, step0, step1, step2, step3, and step4. Each contains a README file and source. Go through each directory sequentially.Finally, even if you went through the tutorial, be sure to look through the code in
rpcstrings. It's very brief but shows you how to pass and return strings via RPC. You'll need to know this for this assignment! -
Create the RPC definition file defining the two functions: add and query.
-
Create a client, hist.c. hist.c contains the main program. Use the demo program as a guide to make it RPC ready. You can use:
rpcgen -C -Sc hist.xto generate server template code. If you do this, be sure to clean it up!!
-
Create a server, hserver.c. hserver.c will contain the two RPC functions that you need to support. You can use
rpcgen -C -Ss hist.xto generate a stubbed-out server. You'll later fill in code to implement the needed functionality. -
Compile everything:
-
Run the RPC compiler:
rpcgen -C hist.xThis will generate the client stub (hist_clnt.c), the server stub (hist_svc.c), and the header file (hist.h). Depending on your definitions, you will probably have another file containing data conversion functions (hist_xdr.c). -
Compile the functions (you only need to use
-lnslon SunOS systems):gcc -g -DRPC_SVC_FG -o hist hist.c hist_clnt.c hist_xdr.c -lnsl gcc -g -DRPC_SVC_FG -o hserver hserver.c hist_svc.c hist_xdr.c -lnsl -
Your process for compilation won't change now even as you'll be fixing the code. Now is a good time to create a makefile. Don't use the one that was automatically generated by rpcgen (it's virtually unreadable and does not handle dependencies correctly - it's a good example of how not to write a makefile) - see step 6 of the RPC tutorial and also this short tutorial on makefiles.
-
-
Add initial functionality to the client (hist). You'll rip out everything from the auto-generated stub except for creating the RPC handle and calling the functions. You'll also rename the parameters to something more sensible.
In main, you will parse the command line options (to validate that the request is valid and has the right number of parameters). Then you'll call the appropriate remote procedure. You won't print the results yet because the server does nothing.
-
At the server, put printf statements in each of the functions, printing the parameters that are being passed. Run make and validate that the correct procedure is being called and the parameters are what you expect.
-
Implement the add function. If efficiency isn't an issue (it isn't), the easiest thing to do is just to use a single linked list.
You may want to have an array of months and dates, each containing a list.
When storing the string that was passed as a parameter, you'll have to allocate new memory for it - the parameter memory will be reclaimed when you return from the procedure. Check out the strdup function (man strdup).
Test add.
-
Implement the query function. It searches for the first event with the given month and date and returns that unless a non-zero ID was passed in. One implementation is to have the ID serve as a request to get the nth entry. The client will keep requesting additional entries until an empty entry is returned (signifying no more events for that date). For example:
id = 0; for (;;) { event = query(id++, month, date); if (event.gotsomething == 0) break; puts(event.name); }You can also have an implementation where each entry contains an ID number associated with it. In this case, the server searches through all the events for the given month and date until it finds the one with a matching ID and then returns the next one. If you go this route, the client will iterate with the following logic (not code!):
id = 0; for (;;) { event = query(id, month, date); if (event.id == 0) break; puts(event.name); id = event.id; }With either scheme, you avoid having to maintain state on the server and avoid returning lists.
-
Don't do a half-assed job. Make sure that your program:
has a simple and clean makefile, not the one that was automatically generated by rpcgen - see the RPC tutorial and also this short tutorial on makefiles.
Also, make sure that the makefile compiles with
-DRPC_SVC_FG. This will ensure that your server does not automatically run in the background. Without this, you're likely to forget that the server runs in the background and you may end up launching dozens of instances of the server as you debug.handles missing arguments gracefully (gives a useful error message or uses sensible defaults).
is cleanly formatted with proper indentation (NO mixing of leading tabs and spaces).
has a reasonable number of comments (not an overabundance)
handles errors gracefully: server not running, deleting non-existent data, querying empty data, adding hundreds or thousands of entries.
detects RPC failures, prints a message and exits.
doesn't look like you just modified sample or auto-generated code and still left the name as DATE_PROG, ADD_PROG, etc. or have the default comments that rpcgen puts in.
make sure that it compiles through make. Run:
make clean makeUse shell scripts to populate it with hundreds of entries. Make sure that you do NOT have fixed limits on the number of entries. Use a script to add thousands of entries. For a bunch of sample data, you can download a file of events.
You can populate your server with a /bin/sh script such as:
while read month date event;do ./hist server_name add $month $date "$event" done <histfileOf course, you should be running the server in another window (or in the background).