diff options
Diffstat (limited to 'reference/C/CONCEPT/rpc.html')
-rw-r--r-- | reference/C/CONCEPT/rpc.html | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/reference/C/CONCEPT/rpc.html b/reference/C/CONCEPT/rpc.html new file mode 100644 index 0000000..e45041c --- /dev/null +++ b/reference/C/CONCEPT/rpc.html @@ -0,0 +1,356 @@ +<title>RPC</title> +<body bgcolor="#ffffcc"> +<hr> +<center><h1>Remote Procedure Calls (RPC).</h1></center> +<hr> +In the normal scope of things, a program can only call a function +that is linked into the executable or provided by a shared library. +RPC allows programs to execute functions in another executing program, cool! +<p> +RPC has a concept of clients and servers. +<ol> +<li>The client issues requests to the server. +<li>Servers perform the requests and return the results. +<li>The data that flows between client and server includes +int, float, strings and structures. +<li>The client and server can be on the same host or different hosts +connected via a network. +<li>The hosts do not have to be the same artitechture. +</ol> + +The RPC <a href=../glossary.html#api>API</a> has three levels of support. +By using the highest level +RPC is responcable for most of the code but is not too flexable. The lowest +level requres more coding but gives the programmer more control over how RPC +functions. +<p> +The easiest way to start with RPC is to use a program called <b>rpcgen</b> +this reads a file that describes the required interface between client and server +and generates C code that you can include in your client and server. + +<pre> + + prog.x --> rpcgen ---> prog.h Header file + ---> prog_clnt.c Client stubs file + ---> prog_svc.c Server stubs file + ---> prog_xdr.c XDR routines (more later). + +</pre> +You write <b>prog.x</b> and rpcgen generates +<b>prog.h prog_clnt.c prog_svc.c prog_xdr.c</b> + +You then write the client and server and link them with the rpcgen code +to complete the RPC system. + +<pre> + + client.c -----> client executable + prog.h ---| + prog_clnt.c ---| + prog_xdr.c ---| + + server.c -----> Server executable + prog.h ---| + prog_svc.c ---| + prog_xdr.c ---| + + +</pre> + +Ok, time for some examples. + +<h3>Calling an RPC server function without passing any arguments.</h3> +This is the simplest form of RPC. + +<p> +<center> +<table bgcolor=ivory width=80%> +<th> +void.x +</th> +<tr> +<td> +<pre> + + /* RPCGEN code decribing the client/server API. */ + + program MJLPROG + { + version MJLVERS + { + void VOID(void) = 1; + + } = 1; + } = 0x20000001; +</pre> +</td> +</tr> +</table> +</center> +<p> + +<b>void.x</b> describes the RPC interface between the client +and server. There are some important items to note here. +<p> +<table><tr> +<td bgcolor=silver> +<pre> +program MJLPROG +{ +} = 0x20000001; +</pre></td> +<td>This is the RPC program number. It is used by the client to +identify the server it intends to use. +It is important that you provide a unique number here. You can see +which values are in use with the Unix command <b>rpcinfo -p</b> or +by looking at <b>/etc/rpc</b>. Please note that the number is supplied +in void.x as a hex value but shown as a decimal value by <b>rpcinfo</b> +One other point, you should only use values in the range 0x20000000 +0x3FFFFFFF as these have been reserved for use local use. +</td> +</tr> +<tr> +<td bgcolor=silver> +<pre> +version MJLVERS +{ +} = 1; +</pre></td> +<td>The RPC Version number.</td> +</tr> +<tr> +<td bgcolor=silver><pre>void VOID(void) = 1;</pre></td> +<td>This defines the only RPC function that the server will provide.</td> +</tr> +</table> +<p> + +<center> +<table bgcolor=ivory width=80%> +<th> +void_client.c +</th> +<tr> +<td> +<pre> + + #include <rpc/rpc.h> + #include "void.h" + + main() + { + CLIENT *pclnt; + void *pVoid; + + char Host[256]; + + /* Get the name of the host running the server. */ + + gethostname(Host, 256); + + /* Connect to the server. */ + + pclnt = clnt_create(Host, MJLPROG, MJLVERS, "udp"); + + /* Issue a request to the server. */ + + void_1(pVoid, pclnt); + + /* Disconnect from the server. */ + + clnt_destroy(pclnt); + + } +</pre> +</td> +</tr> +</table> +</center> + +<p> +<table> +<tr> +<td bgcolor=silver> +<pre> +#include <rpc/rpc.h> + +</pre> +</td> +<td> +Include the standard RPC headers. +</td> +</tr> +<tr> +<td bgcolor=silver> +<pre> +#include "void.h" +</pre> +</td> +<td> +Include the header file generated by <b>rpcgen</b> +</td> +</tr> +<tr> +<td bgcolor=silver> +<pre> +pclnt = clnt_create(); +</pre> +</td> +<td>Connect to the server <b>MJLPROG</b> on <b>Host</b> and return a +pointer to the <b>CLIENT</b> control structure. +</td> +</tr> +<tr> +<td bgcolor=silver> +<pre> +void_1(pVoid, pclnt); +</pre> +</td> +<td> +Call the remote function. +</td> +</tr> +<tr> +<td bgcolor=silver> +<pre> +clnt_destroy(); +</pre> +</td> +<td> +Disconnect from the server. +</td> +</tr> +</table> +<p> + +<center> +<table bgcolor=ivory width=80%> +<th> +void_server.c +</th> +<tr> +<td> +<pre> + + #include <rpc/rpc.h> + #include "void.h" + + void *void_1_svc(void *pVoid, struct svc_req *X) + { + printf("Function called without passing arguments\n"); + } + +</pre> +</td> +</tr> +</table> +</center> + +<p> +<table> +<tr> +<td bgcolor=silver> +<pre> +void *void_1_svc() +</pre> +</td> +<td> +The server function that will be run for the client. +</td> +</tr> +</table> +<p> + +Please note that the server does not have a <b>main()</b>, rpcgen +generates it for you. +<p> +The code can be compiled with the following commands + +<pre> + gcc void_server.c void_svc.c -o void_server + gcc void_client.c void_clnt.c -o void_client +</pre> +<p> +In theory you should be able to start the server and it will +respond everytime the client is executed. I have not included any +error recovery into this example as it makes the code harder to +read. As an exercise try adding the error recovery code yourself :-) + +<h3>Transfer integers between the client and server</h3> + + +<p> +<center> +<table bgcolor=ivory width=80%> +<th> +integer.x +</th> +<tr> +<td> +<pre> + + /* RPCGEN code decribing the client/server API. */ + + program MJLPROG + { + version MJLVERS + { + int INTEGER(int) = 1; + + } = 1; + } = 0x20000001; +</pre> +</td> +</tr> +</table> +</center> + +<p> +<table> +<tr> +<td bgcolor=silver> +<pre> +int INTEGER(int) = 1; +</pre> +</td> +<td> +Server function now accepts an integer and returns an integer. +</td> +</tr> +</table> + + + + +<p> + +<hr> +<h2>See Also:</h2> + +<img src=../../GRAPHICS/whiteball.gif> +<a href=../SYNTAX/void.html>VOID keyword.</a> +<hr> +<p> +<center> +<table border=2 width=80% bgcolor=ivory> +<tr align=center> +<td width=25%> +<a href=../cref.html>Top</a> +</td><td width=25%> +<a href=../master_index.html>Master Index</a> +</td><td width=25%> +<a href=../SYNTAX/keywords.html>Keywords</a> +</td><td width=25%> +<a href="../FUNCTIONS/funcref.htm">Functions</a> +</td> +</tr> +</table> +</center> +<p> + +<hr> +29-Dec-97 +<address>Martin Leslie + + + |