program TESTPROG {
version VERSION {
string TEST(string) = 1;
} = 1;
} = 87654321; 

客户端:

#include <rpc/rpc.h>

CLIENT *clnt_create( const char *host,  

const u_long prognum 

const u_long versnum, 

const char *nettype);

 enum clnt_stat clnt_call(CLIENT *clnt,

                          const u_long procnum,

                          const xdrproc_t inproc,

                          const caddr_t in,

                          const xdrproc_t outproc,

                          caddr_t out,

                          const struct timeval tout);

通过clnt_create里的二个参数:prognumversnum确定调哪一个程序;

然后再通过clnt_call里的参数procnum来确定调程序中的哪个过程。

很多例子里都可以看见客户端程序在clnt_create函数执行之后,就直接开始调用服务端程序的函数了,其实这个函数是被rpcgen封装了的,在这个这个函数中,实际上还是通过clnt_call来实现的:

clnt = clnt_create (host, TESTPROG, VERSION, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
#endif /* DEBUG */

result_1 = test_1(&test_1_arg, clnt);
if (result_1 == (char **) NULL) {
clnt_perror (clnt, "call failed");
}
#ifndef DEBUG
clnt_destroy (clnt); 

test_1(char **argp, CLIENT *clnt)
{
static char *clnt_res;
memset((char *)&clnt_res, 0, sizeof(clnt_res));
if (clnt_call (clnt, TEST,
(xdrproc_t) xdr_wrapstring, (caddr_t) argp,
(xdrproc_t) xdr_wrapstring, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
return (&clnt_res);
} 

服务器端:

svctcp_create/svcudp_create

svc_register(xprt, prognum, versnum, dispatch, protocol)

其中第四个参数很关键,是处理函数:

if (!svc_register(transp, TESTPROG, VERSION, testprog_1, IPPROTO_TCP)) {
fprintf (stderr, "%s", "unable to register (TESTPROG, VERSION, tcp).");
exit(1);
} 

static void  testprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
char *test_1_arg;
} argument;
char *result;
xdrproc_t _xdr_argument, _xdr_result;
char *(*local)(char *, struct svc_req *);

switch (rqstp- case NULLPROC:
(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
return;

case TEST:
_xdr_argument = (xdrproc_t) xdr_wrapstring;
_xdr_result = (xdrproc_t) xdr_wrapstring;
local = (char *(*)(char *, struct svc_req *)) test_1_svc;
break;

default:
svcerr_noproc (transp);
return;
}
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;
} 

svc_run