兩種RPC編程

第一種:
RPC編程首先需要一個.x文件,然後用rpcgen生成客戶端與服務器端程序的c代碼,分別編譯,運行即可。

rpcgen 簡介

rpcgen可以自動生成RPC服務器程序的大多數代碼,它的輸入爲一個規格說明文件,它的輸出爲一個C語言的源程序。規格文件(*.x)包含常量、全局數據類型以及遠程過程的聲明。Rpcgen產生的代碼包含了實現客戶機和服務器程序所需要的大部分源代碼。他包括參數整理、發送RPC報文、參數和結果的外部數據表示以及本地數據表示的轉換等。不過在由rpcgen生成的源文件中,沒有過程的具體實現,所以程序員必須要手工編輯這些文件,實現這些過程。

 

Rpc自動生成的文件

文件名

作用

Makefile.file

該文件用於編譯所有客戶機,服務器代碼

File_clnt.c

該文件包含client_stub,程序員一般不用修改

File_svc.c

該文件包含server_stub,程序員一般不用修改

File.h

該文件包含了從說明中產生的所有XDR類型

File_xdr.c

該文件包含了客戶機和服務器stub所需的XDR過濾器,程序員一般不用修改

File_server.c

如果生成此文件,則該文件包含遠程服務的stub

File_client.c

如果生成此文件,則該文件包含了骨架客戶機程序。

 

Rpcgen的部分選項

-a 生成所有源程序,包括客戶機和服務器源程序。

-C 使用ANSI C標準生成編碼。

-c 生成xdr轉碼C程序。(file_xdr.c)。

-l 生成客戶機stubs。(file_clnt.c

-m 生成服務器stubs,但是不生成main函數。(file_svc.c

-s  rpcgen –C –s tcp file.x,生成服務器stubs,用tcp協議,同時生成了main函數。(file_svc.c

              -h 生成頭文件。

              -Sc 生成骨架客戶機程序,(file_client.c),生成後還需要手動添加代碼。

              -Ss 生成服務器程序,(file_server.c),生成後還需要手動添加代碼。

Rpcgen –C  file.x 生成file_xdr.c,file.h,Makefile.file,file_svc.cfile_client.c

Rpcgen –C –a file.x 比上面多生成了2個文件,file_server.cfile_client.c

 

Rpcgen示例程序

規格文件(math.x

/* filename: math.x */

const ADD = 0;

const SUB = 1;

const MUL = 2;

const DIV = 3;

struct MATH

{

    int op; /* 0-ADD, 1-SUB, 2-MUL, 3-DIV */

    float arg1;

    float arg2;

    float result;

};

program MATH_PROG

{

    version MATH_VER

    {

        struct MATH MATH_PROC(struct MATH) = 1;

    } = 2;

} = 0x20000001;

 

rpcgen –C –a math.x 生成7個文件,math.hmath_xdr.cmath_svc.cmath_clnt.cMakefile.mathmath_client.cmath_server.c

math_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 "math.h"

void math_prog_2(char *host)

{

              CLIENT *clnt;

              struct MATH  *result_1;

              struct MATH  math_proc_2_arg;

    /* 2006/07/04 Dongyy Add -> */

    char c;

    printf("choose the operation:/n/t0---ADD/n/t1---SUB/n/t2---MUL/n/t3---DIV/n");

    c = getchar();

    switch(c) {

        case '0':

            math_proc_2_arg.op = ADD;

            break;

        case '1':

            math_proc_2_arg.op = SUB;

            break;

        case '2':

            math_proc_2_arg.op = MUL;

            break;

        case '3':

            math_proc_2_arg.op = DIV;

            break;

        default:

            printf("error:operate/n");

            exit(1);

    }

    printf("input the first number:");

    scanf("%f", &math_proc_2_arg.arg1);

    printf("input the second number:");

    scanf("%f", &math_proc_2_arg.arg2);

    /* <- 2006/07/04 Dongyy Add */

 

#ifndef   DEBUG

              clnt = clnt_create (host, MATH_PROG, MATH_VER, "udp");

              if (clnt == NULL) {

                             clnt_pcreateerror (host);

                             exit (1);

              }

#endif    /* DEBUG */

 

              result_1 = math_proc_2(&math_proc_2_arg, clnt);

              if (result_1 == (struct MATH *) NULL) {

                             clnt_perror (clnt, "call failed");

              }

#ifndef   DEBUG

              clnt_destroy (clnt);

#endif    /* DEBUG */

    /* 2006/07/04 Dongyy Add -> */

    printf("The Result is %.3f /n", result_1->result);

    /* <- 2006/07/04 Dongyy Add */

}

int main (int argc, char *argv[])

{

              char *host;

 

              if (argc < 2) {

                             printf ("usage: %s server_host/n", argv[0]);

                             exit (1);

              }

              host = argv[1];

              math_prog_2 (host);

    exit (0);

}

math_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 "math.h"

 

struct MATH *

math_proc_2_svc(struct MATH *argp, struct svc_req *rqstp)

{

              static struct MATH  result;

 

              /*

               * insert server code here

               */

   

    /* 2006/07/04 Dongyy Add -> */

    switch(argp->op){

        case ADD:

            result.result = argp->arg1 + argp->arg2;

            break;

        case SUB:

            result.result = argp->arg1 - argp->arg2;

            break;

        case MUL:

            result.result = argp->arg1 * argp->arg2;

            break;

        case DIV:

            result.result = argp->arg1 / argp->arg2;

            break;

        default:

            break;

    }

    /* <- 2006/07/04 Dongyy Add */

 

              return &result;

}

紅色字體部分爲用rpcgen生成代碼後,手動添加的代碼。

添加完後,執行make –f makefile.math 編譯生成math_clientmath_server,在命令行運行math_server &,然後運行math_client 127.0.0.1,按照提示輸入內容就OK了。

 

參考書籍《Linux C 高級程序員指南》

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=88991


第二種:在服務器端註冊,在客戶端調用:
#include   <stdio.h> 
#include   <rpc/rpc.h> 
#include   <utmp.h> 
#include   "rpc.h" 
unsigned   int*   nuser(unsigned   int*   ui) 
  { 
                  printf("haha,your   input   value   =   %d/n",*ui); 
                  *ui=*ui+1; 
                  return   ui; 
  };  
main() 
  { 
          registerrpc(DEMOPROG,   DEMOVER,   DEMOFUNC, 
                  nuser,   xdr_u_int,   xdr_u_int); 
          svc_run();                 /*   Never   returns   */ 
          fprintf(stderr,   "Error:   svc_run   returned!/n"); 
          exit(1); 
  }  

#include   <stdio.h> 
#include   <rpc/rpc.h> 
#include   <utmp.h> 
#include   "rpc.h" 
  
main(argc,   argv) 
          int   argc; 
          char   **argv; 
  { 
          unsigned   long   nusers=0; 
          int   stat=0; 
          unsigned   int   val=0; 
          if   (argc   !=   3)   { 
                  fprintf(stderr,   "usage:   nusers   hostname/n"); 
                  exit(-1); 
          } 
          val   =   atoi(argv[2]); 
          printf("val   =   %d/n",val); 
          if   (stat   =   callrpc(argv[1], 
                  DEMOPROG,   DEMOVER,   DEMOFUNC, 
                  xdr_u_int,&val,   xdr_u_int,   &nusers)   !=   0)   { 
                          clnt_perrno(stat); 
                          exit(1); 
          } 
          printf("%d   users   on   %s/n",   nusers,   argv[1]); 
          exit(0); 
  }  

//rpc.h
#define   DEMOPROG                 0x20000001 
#define   DEMOVER                   0x1 
#define   DEMOFUNC                 0x1  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章