summaryrefslogtreecommitdiff
path: root/reference/C/CONCEPT/rpc.html
blob: e45041c56ae7c081a61d36911fdf701dd89cb43a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
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 &lt;rpc/rpc.h&gt;
  #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 &lt;rpc/rpc.h&gt;

</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