|
Network Programming This website demonstrates using wikis as teaching and learning tool. The course instructor is happy to share the teaching materials here with those who find it readable. |
Lecture /
Network Programming in C and UNIX - RPCA Network Programming Lecture by Steven Choy Lecture Overview: In this lecture, you learn the concepts underlying a remote procedure call (RPC), which is a popular model for client-server communication. We also provide a programming example to show how it works. Introduction
Network communication with the remote procedure call
The RPC MechanismThe following summarizes the RPC mechanism:
1) The client provides the arguments and calls the client stub in the normal way.
2) The client stub builds (marshals) a message (call request) and sends it to the Operating System and network kernel (communication module).
3) The kernel sends the message to the remote kernel. The remote kernel receives the message and gives it to the server dispatcher.
4) The dispatcher selects the appropriate server stub.
5) The server stub unpacks (unmarshals) the parameters and calls the corresponding server procedure.
6) The server procedure does the work and returns the result to the server stub.
7) The server stub packs (marshals) it in a message (call return) and sends it to the Operating System and network kernel.
8) The remote (receiver) kernel sends the message to the client kernel.
9) The client kernel gives the message to the client stub.
10) The client stub unpacks (unmarshals) the result and returns to client.
RPC ImplementationThe three main tasks in RPC implementation are: interface processing, communication handling, and binding.
The interface compiler (called RPC generator in Sun RPC) processes interface definitions written in an interface definition language.
After executing, the interface compiler generates client and server stub procedures with marshalling and unmarshalling operations.
TCP and UDP communications are supported to transmit and receive request and reply messages within the Internet environment.
Binding specifies a mapping process from a name to a particular object, which is usually identified by a communication ID.
Binding is important, because an interface definition specifies a textual service name for use by clients and servers. We need a binder, which is a separate service that maintains a table containing mappings from service names to server ports. Moreover, a client’s request message must be addressed to a server port. Note that all other services depend on the binder service. If we did not have the binding service, we would not know how to access remote services.
Servers use two binder interfaces, Register and Withdraw, and clients use one binder interface, Portlookup.
The procedure
Register (String ServiceName, Port ServerPort, int version)
is used to register the name of a server process ServiceName with its server’s port ServerPort. Note that the integer version is used to record the number of versions registered in the server.
The procedure
Withdraw (String ServiceName, Port ServerPort, int version)
is to withdraw the registration.
The procedure
Portlookup (String ServiceName, int version)
is used by a client to search the corresponding ServerPort by given ServerName.
RPC Programming
1) rpcgen, an interface compiler that takes the definition of a remote procedure interface and generates a client stub and a server stub.
2) XDR (External Data Representation), the interface definition language, which is a standard way of encoding data in a portable fashion between different systems.
3) A run-time library that handles all of the details.
The client calls remote services using RPC. The server has the following two functions:
bin_date_1: This returns the current time as the number of seconds since 00:00:00 GMT, January 1, 1970.
str_date_1: This takes a long integer value from the above function and converts it into an ASCII string that is human readable format.
date.x is a RPC specification file that specifies the signatures of the remote server procedures in date_server.c. The content of date.x is listed below:
The file declares both of the procedures and specifies the argument and return values for each.
It also assigns a procedure number to each function (1 and 2), along with a program number (0x31234567) and a version number (1).
Procedure numbers start at 0. Every remote program and version must define procedure number 0 as the ‘null procedure’. It does not require any arguments and returns nothing. The rpcgen compiler automatically generates it. The function of this procedure number is to allow a client to call it to verify that the particular program and version exist. It is also useful for clients to calculate the round-trip time, since if a client calls it, it does nothing and returns a null reply to the client. Thus, the time taken to call an RPC with procedure number 0 is the round-trip communication time.
The rpcgen compiler generates the actual remote procedure names by converting the names BIN_DATE and STR_DATE to bin_date_1 and str_date_1 respectively. The methodology used is to change the name from uppercase to lowercase and then append an underscore and the version number. For example, if the procedure name in the RPC specification file is ABCDE with version number 2, the actual remote procedure name is abcde_2.
We define the remote procedure BIN_DATE as taking no arguments (void) and returning a long integer result (int). Also, the remote procedure STR_DATE takes a long integer argument (int) and returns a string result (static char). We explain later why we use static char but not char. Note that Sun RPC allows at most one single argument and returns at most one single result. If more arguments are expected, we have to use a data structure as the argument. Also, if more than one value is returned, a data structure must be used as the return value.
To execute the rpcgen compiler, you should type the following command:
Then the rpcgen compiler generates three different files from date.x — date_svc.c, date.h, and date_clnt.c.
The content of the file date.h is shown below:
It defines our function bin_date_1 as returning a pointer to a long integer.
It also defines our function str_date_1 as returning a pointer to a character pointer.
date_svc.c and date_clnt.c are the client and server stub procedures respectively. They are used to compile with the client and server processes when we compile.
To create a client program from the client main function chkdate.c in the client side, you should type the following commands in the following order:
>cc –c chkdate.c chkdate.o >cc –c date_clnt.c –o date_clnt.o >cc –o chkdate chkdate.o date_clnt.o -lrpc Note that rpc is the RPC run-time library.
On the server side, you should type the following commands in the following order:
>cc –c date_server.c date_server.o >cc –c date_svc.c –o date_svc.o >cc –o date_server date_server.o date_svc.o -lrpc
The program flow is simple.
First, check the existence of the second argument, which should contain the name of the remote server.
Second, call clnt_create to create an RPC handle to the specified program (the second argument) and version (the third argument) on a host. We also need to specify which communication protocol we used. It is usually either TCP or UDP. In our example, we used TCP, so the fourth argument is tcp. Note that the first argument is the name of the remote server. After executing the function call clnt_create, we have the handle.
Third, we can call the remote procedures bin_date_1 and str_date_1 for that particular program and version.
Fourth, When we finish executing the two remote procedures, we call clnt_destroy to destroy the RPC handle.
As mentioned, the server program is just a set of functions and is not a main program. The flow is very simple. The first function just calls the time function to get the current time, and the second function converts it into a human readable format. Note that the return values must be static variables, because if we do not use static variables, their values would be undefined after the return statement passes control back to the server stub that calls our remote procedure.
In the server side, we execute the server program as follows:
> date_server &
Note that & means background execution.
On the client side, we execute the client program and obtain the following daytime result from the server:
> chkdate localhost time on host localhost = 1016692751 time on host localhost = Thu Mar 21 14:39:11 2009 Note that localhost is used as the remote server for our testing.
Tools and ReferencesThanks for ReadingIf you would rather like to have this lecture note in printed format, please click the print action link in the top right corner. If you find any problem in this lecture note, please feel free to tell Steven via steven@findaway.hk. |