rpcgen编译器的使用

rpcgen是一个编译器,可以方便的让你写rpc程序,自动生成网络连接的接口代码,免去你手写这些代码的麻烦。也可以说是一个rpc自动代码生成工具。

1. 编写-widebright.x文件,这需要采用“RPC Language”, 就是rpcgen使用的一种语言,和c语言很类似,是“XDR language” 的扩展,关于这个语言的定义和使用自己参考 “rpcgen Programming Guide”了。

------------widebright.x文件内容----------------------------
/*
* widebright.x: Remote widebright protocol. ^_^
*/

/*
* 以百分号开始的行,rpcgen将原封不动的写到输出文件中去
*/
%#define MAX_NAME_LENGTH 64

/*
* XDR语言中数组用尖括号 , 同时char * 要写成 string
*/
struct widebright_info{
unsigned int age;
string name;

};
typedef widebright_info widebright_info_t;


program WIDEBRIGHT_PROG {
     version   WIDEBRIGHT_RPC_VERSION {
             int   GET_AGE(string) = 1;
             string GET_PROFILE(void) = 2;
             widebright_info_t GET_ALL() = 3;
      } = 1;
} = 99;

----------------------------------------------------

2. 执行 “rpcgen widebright.x” 命令
将自动生成如下文件:
widebright.h         定义头文件
widebright_clnt.c       (client side stubs)客户端绑定函数
widebright_svc.c        (server side stubs) 服务器端绑定函数
widebright_xdr.c         XDR 转换函数

---------widebright.h 文件内容-----------------------------------
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/

#ifndef _WIDEBRIGHT_H_RPCGEN
#define _WIDEBRIGHT_H_RPCGEN

#include


#ifdef __cplusplus
extern "C" {
#endif

#define MAX_NAME_LENGTH 64

struct widebright_info {
        u_int age;
        char *name;
};
typedef struct widebright_info widebright_info;

typedef widebright_info widebright_info_t;

#define WIDEBRIGHT_PROG 99
#define WIDEBRIGHT_RPC_VERSION 1

#if defined(__STDC__) || defined(__cplusplus)
#define GET_AGE 1
extern int * get_age_1(char **, CLIENT *);
extern int * get_age_1_svc(char **, struct svc_req *);
#define GET_PROFILE 2
extern char ** get_profile_1(void *, CLIENT *);
extern char ** get_profile_1_svc(void *, struct svc_req *);
#define GET_ALL 3
extern widebright_info_t * get_all_1(void *, CLIENT *);
extern widebright_info_t * get_all_1_svc(void *, struct svc_req *);
extern int widebright_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);

#else /* K&R C */
#define GET_AGE 1
extern int * get_age_1();
extern int * get_age_1_svc();
#define GET_PROFILE 2
extern char ** get_profile_1();
extern char ** get_profile_1_svc();
#define GET_ALL 3
extern widebright_info_t * get_all_1();
extern widebright_info_t * get_all_1_svc();
extern int widebright_prog_1_freeresult ();
#endif /* K&R C */

/* the xdr functions */

#if defined(__STDC__) || defined(__cplusplus)
extern bool_t xdr_widebright_info (XDR *, widebright_info*);
extern bool_t xdr_widebright_info_t (XDR *, widebright_info_t*);

#else /* K&R C */
extern bool_t xdr_widebright_info ();
extern bool_t xdr_widebright_info_t ();

#endif /* K&R C */

#ifdef __cplusplus
}
#endif

#endif /* !_WIDEBRIGHT_H_RPCGEN */


-----------widebright_clnt.c   文件内容---------------------------------------------
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/

#include /* for memset */
#include "widebright.h"
#define MAX_NAME_LENGTH 64

/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };

int *
get_age_1(char **argp, CLIENT *clnt)
{
        static int clnt_res;

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

char **
get_profile_1(void *argp, CLIENT *clnt)
{
        static char *clnt_res;

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

widebright_info_t *
get_all_1(void *argp, CLIENT *clnt)
{
        static widebright_info_t clnt_res;

        memset((char *)&clnt_res, 0, sizeof(clnt_res));
        if (clnt_call (clnt, GET_ALL,
                (xdrproc_t) xdr_void, (caddr_t) argp,
                (xdrproc_t) xdr_widebright_info_t, (caddr_t) &clnt_res,
                TIMEOUT) != RPC_SUCCESS) {
                return (NULL);
        }
        return (&clnt_res);
}


-------------widebright_svc.c 文件内容---------------
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/

#include "widebright.h"
#include
#include
#include
#include
#include
#include
#include

#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif
#define MAX_NAME_LENGTH 64

static void
widebright_prog_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
        union {
                char *get_age_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 GET_AGE:
                _xdr_argument = (xdrproc_t) xdr_wrapstring;
                _xdr_result = (xdrproc_t) xdr_int;
                local = (char *(*)(char *, struct svc_req *)) get_age_1_svc;
                break;

        case GET_PROFILE:
                _xdr_argument = (xdrproc_t) xdr_void;
                _xdr_result = (xdrproc_t) xdr_wrapstring;
                local = (char *(*)(char *, struct svc_req *)) get_profile_1_svc;
                break;

        case GET_ALL:
                _xdr_argument = (xdrproc_t) xdr_void;
                _xdr_result = (xdrproc_t) xdr_widebright_info_t;
                local = (char *(*)(char *, struct svc_req *)) get_all_1_svc;
                break;

        default:
                svcerr_noproc (transp);
                return;
        }
        memset ((char *)&argument, 0, sizeof (argument));
        if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument)) {
                svcerr_decode (transp);
                return;
        }
        result = (*local)((char *)&argument, rqstp);
        if (result != NULL && !svc_sendreply(transp, _xdr_result, result)) {
                svcerr_systemerr (transp);
        }
        if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) {
                fprintf (stderr, "%s", "unable to free arguments");
                exit (1);
        }
        return;
}

int
main (int argc, char **argv)
{
        register SVCXPRT *transp;

        pmap_unset (WIDEBRIGHT_PROG, WIDEBRIGHT_RPC_VERSION);

        transp = svcudp_create(RPC_ANYSOCK);
        if (transp == NULL) {
                fprintf (stderr, "%s", "cannot create udp service.");
                exit(1);
        }
        if (!svc_register(transp, WIDEBRIGHT_PROG, WIDEBRIGHT_RPC_VERSION, widebright_prog_1, IPPROTO_UDP)) {
                fprintf (stderr, "%s", "unable to register (WIDEBRIGHT_PROG, WIDEBRIGHT_RPC_VERSION, udp).");
                exit(1);
        }

        transp = svctcp_create(RPC_ANYSOCK, 0, 0);
        if (transp == NULL) {
                fprintf (stderr, "%s", "cannot create tcp service.");
                exit(1);
        }
        if (!svc_register(transp, WIDEBRIGHT_PROG, WIDEBRIGHT_RPC_VERSION, widebright_prog_1, IPPROTO_TCP)) {
                fprintf (stderr, "%s", "unable to register (WIDEBRIGHT_PROG, WIDEBRIGHT_RPC_VERSION, tcp).");
                exit(1);
        }

        svc_run ();
        fprintf (stderr, "%s", "svc_run returned");
        exit (1);
        /* NOTREACHED */
}


-----------widebright_xdr文件内容---------------------------------------
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/

#include "widebright.h"
#define MAX_NAME_LENGTH 64

bool_t
xdr_widebright_info (XDR *xdrs, widebright_info *objp)
{
        register int32_t *buf;

         if (!xdr_u_int (xdrs, &objp->age))
                 return FALSE;
         if (!xdr_string (xdrs, &objp->name, MAX_NAME_LENGTH))
                 return FALSE;
        return TRUE;
}

bool_t
xdr_widebright_info_t (XDR *xdrs, widebright_info_t *objp)
{
        register int32_t *buf;

         if (!xdr_widebright_info (xdrs, objp))
                 return FALSE;
        return TRUE;
}
--------------------------------------------


3.   采用rpcgen的下面这两个选项生成例子程序。
-Sc             generate sample client code that uses remote procedures
-Ss             generate sample server code that defines remote procedures

[widebright@ ddddddd]# rpcgen -Sc -o widebrihgt_client.c widebright.x
[widebright@ ddddddd]# rpcgen -Ss -o widebrihgt_server.c widebright.x

------------widebrihgt_client.c文件内容--------------
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include "widebright.h"
#define MAX_NAME_LENGTH 64


void
widebright_prog_1(char *host)
{
        CLIENT *clnt;
        int *result_1;
        char * get_age_1_arg;
        char * *result_2;
        char *get_profile_1_arg;
        widebright_info_t *result_3;
        char *get_all_1_arg;

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

        result_1 = get_age_1(&get_age_1_arg, clnt);
        if (result_1 == (int *) NULL) {
                clnt_perror (clnt, "call failed");
        }
        result_2 = get_profile_1((void*)&get_profile_1_arg, clnt);
        if (result_2 == (char **) NULL) {
                clnt_perror (clnt, "call failed");
        }
        result_3 = get_all_1((void*)&get_all_1_arg, clnt);
        if (result_3 == (widebright_info_t *) NULL) {
                clnt_perror (clnt, "call failed");
        }
#ifndef DEBUG
        clnt_destroy (clnt);
#endif   /* DEBUG */
}


int
main (int argc, char *argv[])
{
        char *host;

        if (argc < 2) {
                printf ("usage: %s server_host\n", argv[0]);
                exit (1);
        }
        host = argv[1];
        widebright_prog_1 (host);
exit (0);
}

-------------widebrihgt_server.c文件内容-------------------
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include "widebright.h"
#define MAX_NAME_LENGTH 64

int *
get_age_1_svc(char **argp, struct svc_req *rqstp)
{
        static int result;

        /*
         * insert server code here
         */

        return &result;
}

char **
get_profile_1_svc(void *argp, struct svc_req *rqstp)
{
        static char * result;

        /*
         * insert server code here
         */

        return &result;
}

widebright_info_t *
get_all_1_svc(void *argp, struct svc_req *rqstp)
{
        static widebright_info_t result;

        /*
         * insert server code here
         */

        return &result;
}


4.
修改widebrihgt_client.c 和widebrihgt_server.c 文件,补全服务器端和客户端调用的代码。
可以参考 “Remote Procedure Call Programming Guide” 的说明

--------修改后的widebrihgt_server.c 文件如下---------------------
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include
#include "widebright.h"
#define MAX_NAME_LENGTH 64

char   widebright_descriptions[256]="widebright is a good boy ^_^";
char name []="widebright";
int *
get_age_1_svc(char **name, struct svc_req *rqstp)
{
        static int age;

        /*
         * insert server code here
         */
        if ( 0 == strcmp ( *name, "widebright"))
        {
            age =24;
       }else {
             age =0;
        }


        return &age;
}

char **
get_profile_1_svc(void *argp, struct svc_req *rqstp)
{
        static char * description;
        /*
         * insert server code here
         */
       description = widebright_descriptions ;
        return &description;
}

widebright_info_t *
get_all_1_svc(void *argp, struct svc_req *rqstp)
{
        static widebright_info_t info;

        /*
         * insert server code here
         */

         info.age = 24;
         info.name =name;
/*
         printf ("name length=%d",strlen(info.name));
         strcpy (info.name , "widebright");
*/

   return &info;
}

------------修改后的widebrihgt_client.c文件内容--------------
/*
* This is sample code generated by rpcgen.
* These are only templates and you can use them
* as a guideline for developing your own functions.
*/

#include
#include "widebright.h"
#define MAX_NAME_LENGTH 64


void
widebright_prog_1(char *host)
{
        CLIENT *clnt;
        int *result_1;
        char * get_age_1_arg;
        char name [256] ="widebright";
        char name2 [256] ="unkown";
        char * *result_2;
        char *get_profile_1_arg;
        widebright_info_t *result_3;
        char *get_all_1_arg;

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

      get_age_1_arg   = name ;
        result_1 = get_age_1( &get_age_1_arg, clnt);
        if (result_1 == (int *) NULL) {
                clnt_perror (clnt, "call failed");
        }
        printf ("%s 's age is %d.\n" , name,*result_1 );

       get_age_1_arg   = name2 ;
        result_1 = get_age_1(&get_age_1_arg, clnt);
        if (result_1 == (int *) NULL) {
                clnt_perror (clnt, "call failed");
        }
        printf ("%s 's age is %d.\n" , name2,*result_1 );


        result_2 = get_profile_1((void*)&get_profile_1_arg, clnt);
        if (result_2 == (char **) NULL) {
                clnt_perror (clnt, "call failed");
        }

        printf ("widebright's description:%s\n" , *result_2 );


        result_3 = get_all_1((void*)&get_all_1_arg, clnt);
        if (result_3 == (widebright_info_t *) NULL) {
                clnt_perror (clnt, "call failed");
        }

       printf ("widebright's age:%d\n" ,   (*result_3).age );
       printf ("widebright's name:%s\n" ,   (*result_3).name );

#ifndef DEBUG
        clnt_destroy (clnt);
#endif   /* DEBUG */
}


int
main (int argc, char *argv[])
{
        char *host;

        if (argc < 2) {
                printf ("usage: %s server_host\n", argv[0]);
                exit (1);
        }
        host = argv[1];
        widebright_prog_1 (host);
exit (0);
}

-------------------------------------------------------------------------------


5.
编译生成服务器端程序 ,
gcc widebright_xdr.c widebright_svc.c widebrihgt_server.c -o widebrihgt_server
编译生成客户端程序
gcc widebright_clnt.c widebright_xdr.c widebrihgt_client.c -o widebrihgt_client


然后用scp命令复制widebrihgt_server到远程机器上运行
[widebright ddddddd]# ./widebrihgt_server &
[1] 11531

然后在本地运行客户机widebrihgt_client 去连接远程程序,这里是连接本地机器上的
[widebright ddddddd]# ./widebrihgt_client 127.0.0.1
widebright 's age is 24.
unkown 's age is 0.
widebright's description:widebright is a good boy ^_^
widebright's age:24
widebright's name:widebright


可以看到远程的过程已经得到正确的调用了

你可能感兴趣的:(RPC)