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里的二个参数:prognum和versnum确定调哪一个程序;
然后再通过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