Transcript Linux

Linux RPC
Comer Chapter 21
(RPCgen Concept)
RFC 1057 – RPC Spec.
UNIX Network Programming - Stevens
1
Using Remote Procedure Calls
• As a program specification technique
• For program specification and as an
abstraction during design
• Explicitly in the implementation
• For design and implementation, from scratch
• For design and implementation, with
standard libraries
• For automated implementation
2
RPC Programming Mechanisms
ONC (Open Network Computing)
• XDR library routines for data conversion
• XDR library routines for complex data
structures
• RPC run-time library routines
• Program generator tool
3
RPC Programming Process
• Dividing the program into local and remote
procedures.
Proc A
Client Stub
RPC
Server Stub
Proc B
4
RPC Dispatching
(Procedure Location)
Proc A1
Proc A2
RPC
RPC
Dispatcher
Server Stub
Server Stub
Proc B1
Proc B2
Client Stub
Client Stub
5
RPC Interface Specification
Proc A
RPC
Client Iface
Client comm
Server Comm
Server Iface
Proc B
6
RPCgen Input and Output
• Input
– Q.x
Interface specification file
• Output
– Q.h
– Q_xdr.cpp
– Q_clnt.cpp
– Q_svc.cpp
Declarations header file
XDR procedure calls used to
marshal arguments
Client-side communications stub
Server-side communications stub
7
RPC Process Flow
Client
application
Client
interface
Q_clnt.cpp
Q.h
Q.x
rpcgen
compile
Client
compile
Server
Q_xdr.cpp
Q_svc.cpp
Remote
procedures
Server
interface
8
RPC General Build Procedure
Develop Interface
Develop Client
Develop Server
9
Developing the Interface
MyApp.x
RPCgen
MyApp_clnt.c
Client Stub
MyApp.h
MyApp_xdr.c
MyApp_svc.c
Server Stub
10
Developing the Server
MyApp.x
RPCgen
MySrvr.c
MyApp_xdr.c
MyApp.h
MyApp_svc.c
Server Stub
C Compiler
Linker
MySrvr.exe
11
Developing the Client
MyApp.idl
RPCgen
MyClnt.c MyApp_xdr.c
MyApp.h
MyApp_clnt.c
Client Stub
C Compiler
Linker
MyClnt.exe
12
How the Server Prepares for a
Connection
•
•
•
•
•
•
(Be certain that Portmap is running)
Create UDP service
Register UDP service with Portmap
Create TCP service
Register TCP service with Portmap
Run service...
– Uses select( ) to monitor ports.
13
Start Portmap
Portmap is included in all Linux distributions as a
standard server.
Under Red Hat Fedora
Open services applet ,select portmap and start
From command line (as root)
/sbin/services portmap start
Other distributions should be similar
14
Server concurrency mode
RPC servers can be created in either single
threaded or multi-threaded mode.
Servers automatically create and (when done)
destroy a thread for each incoming
connection.
15
Register the Server Program
svc_register(port#, SERV#, VER#, serv_func,
proto#);
port#: port on which the service is active
SERV#: unique number for the service
VER#: version for this particular service
serv_func: name by which this function is
called
proto#: IPPROTO_UDP or IPPROTO_TCP
16
How the Client Establishes a
Connection
•
•
•
•
Make a Remote Procedure Call
Find the Server Host Computer
Find Server Process Port # (through Portmap)
Create a (connection) to the Server Process
17
How the Client Establishes a
Connection
clnt_create(server, SERV#,
VER#, proto#);
remote procedure call...
Clnt_destroy(CLIENT);
18
Example #1
• Temperature Server (Fahrenheit to
Centigrade)
– Parameters passed as integers
– TCP / IP port connection
• Source files:
– temp.x
– Tclient.c
– tempServer.c
19
temp.x
program TEMPSERV {
version TEMPVERS {
int TempConv(int) = 1;
//procedure number
} = 1;
//version
number
} = 77;
//program
number
20
TClient.c
#include <stdio.h>, <stdlib.h>, <string.h>
#include <rpc/rpc.h>
#include "temp.h"
#define YES 0
#define NO 1
void main (int argc, char *argv[])
{
int tempconvert(int temp, char *srvr);
int temperature, nuTemp;
int loopFlag;
char srvr[25];
CLIENT * cl;
21
TClient.c (cont)
strcpy (srvr, argv[1]);
cl = clnt_create(srvr, TEMPSERV, TEMPVERS,
"tcp");
loopFlag = YES;
while(loopFlag == YES)
{
printf("Enter temperature in Faherenheit
(-999 to quit)");
scanf ("%d", &temperature);
ans = tempconv_1(&temperature, cl);
22
TClient.c (cont)
if (ans != NULL)
nuTemp = * ans;
if (temperature == -999 || temperature == -9999)
{
loopFlag = NO;
printf ("Goodbye...\n");
continue;
}
printf("That’s %2d in centigrade\n", nuTemp);
}
clnt_destroy(cl);
return 0;
}
23
tempServer.c
#include <stdlib.h>, <unistd.h>, <stdio.h>
#include <rpc/rpc.h>, "temp.h"
static int count;
static int nuTemp;
int *tempconv_1_svc (int *val, struct
svc_req * rqst)
{
int oldTemp;
oldTemp = *val;
24
tempServer.c
if (oldTemp == -9999)
{
printf("We're shutting down...\n");
exit (0);
}
printf("We got a temperature of %d, ", oldTemp);
count++;
nuTemp = (int)((5*(oldTemp -32)) / 9.0);
printf("and we returned a value of %d\n", nuTemp);
sleep(1);
return (&nuTemp);
}
25
Files created with rpcgen
• Input:
– temp.x
• Output
– temp.h
– temp_xdr.c (NULL file)
– temp_clnt.c
– temp_svc.c
26
temp.h
#include <rpc/rpc.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TEMPSERV 77
#define TEMPVERS 1
#if defined(__STDC__) || defined(__cplusplus)
#define TempConv 1
extern int * tempconv_1(int *, CLIENT *);
extern int * tempconv_1_svc(int *, struct svc_req *);
extern int tempserv_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#ifdef __cplusplus}
#endif
#endif /* !_TEMP_H_RPCGEN */
27
temp_xdr.c
#include <rpc/rpc.h>
#include "temp.h"
28
temp_clnt.c
#include <memory.h> /* for memset */
#include "temp.h“
/* Default timeout can be changed using
clnt_control() */
static struct timeval
TIMEOUT = { 25, 0 };
int *tempconv_1(int *argp, CLIENT *clnt){
static int clnt_res;
memset((char *)&clnt_res, 0, sizeof(clnt_res));
29
temp_clnt.c (cont)
if (clnt_call (clnt, TempConv,
(xdrproc_t) xdr_int, (caddr_t)
argp,
(xdrproc_t) xdr_int,
(caddr_t) &clnt_res, TIMEOUT) !=
RPC_SUCCESS)
{
return (NULL);
}
return (&clnt_res);}
30
temp_svc.c
#include
#include
#include
#include
#include
#include
#include
#include
"temp.h“
<stdio.h>
<stdlib.h>
<rpc/pmap_clnt.h>
<string.h>
<memory.h>
<sys/socket.h>
<netinet/in.h>
#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif
31
temp_svc.c (cont)
static void tempserv_1(struct svc_req *rqstp, register SVCXPRT *transp){
union {
int tempconv_1_arg;
} argument;
char *result;
xdrproc_t _xdr_argument, _xdr_result;
char *(*local)(char *, struct svc_req *);
switch (rqstp->rq_proc) {
case NULLPROC:
(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
return;
case TempConv:
_xdr_argument = (xdrproc_t) xdr_int;
_xdr_result = (xdrproc_t) xdr_int;
local = (char *(*)(char *, struct svc_req *)) tempconv_1_svc;
break;
default:
svcerr_noproc (transp);
32
return; }
temp_svc.c (cont)
memset ((char *)&argument, 0, sizeof (argument));
if (!svc_getargs (transp, (xdrproc_t) _xdr_argument,
(caddr_t) &argument)) {
svcerr_decode (transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, (xdrproc_t)
_xdr_result, result)) {
svcerr_systemerr (transp);
}
if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument,
(caddr_t) &argument)) {
fprintf (stderr, "%s", "unable to free arguments");
exit (1);
}
return;
}
33
temp_svc.c (cont)
int main (int argc, char **argv){
register SVCXPRT *transp;
pmap_unset (TEMPSERV, TEMPVERS);
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL) {
fprintf (stderr, "%s", "can’t create udp
service.");
exit(1);
}
if (!svc_register(transp, TEMPSERV, TEMPVERS,
tempserv_1, IPPROTO_UDP)) {
fprintf (stderr, "%s", "unable to register
(TEMPSERV, TEMPVERS, udp).");
exit(1);
}
34
temp_svc.c (cont)
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
if (transp == NULL) {
fprintf (stderr, "%s", "cannot create tcp
service.");
exit(1);
}
if (!svc_register(transp, TEMPSERV, TEMPVERS,
tempserv_1, IPPROTO_TCP)) {
fprintf (stderr, "%s", "unable to register
(TEMPSERV, TEMPVERS, tcp).");
exit(1);
}
svc_run ();
fprintf (stderr, "%s", "svc_run returned");
exit (1);
/* NOTREACHED */}
35
Sample Client Output
D:\data\RPC\onrpc_temp\client\Debug>client
Enter the temperature in Faherenheit (-999
That would be 0 in centigrade
Enter the temperature in Faherenheit (-999
That would be 37 in centigrade
Enter the temperature in Faherenheit (-999
That would be 100 in centigrade
Enter the temperature in Faherenheit (-999
Goodbye...
localhost
to quit)32
to quit)100
to quit)212
to quit)-9999
D:\data\RPC\onrpc_temp\client\Debug>
36
Sample Server Output
D:\data\RPC\examples\onrpc_temp\server\Debug>server
We got a temperature of 32, and we returned a value of 0
We got a temperature of 100, and we returned a value of 37
We got a temperature of 212, and we returned a value of 100
We're shutting down...
D:\data\RPC\examples\onrpc_temp\server\Debug>
37
Summary
• Linux RPC Implementation models SUN
ONCRPC functionality
• RPC specific programming limited to linking
original applications code with rpcgen
interface code.
38