文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>实现Linux环境下编程RPC通信之个人..

实现Linux环境下编程RPC通信之个人..

时间:2010-09-28  来源:xiaovfight

首先博主抛出一个疑问,如何实现windows和linux之间的rpc通信,这两个异构的系统如何才能建立变量传递通道,这相当困扰博主,如有好心人指点,将不胜感激。

好了,现在切入正题:今天博主在linux环境下实现了一个小小RPC通信,按照惯例,做一下总结吧。

原先博主用的是Red hat9,安装完red hat后不想系统不带GCC,然后博主跑遍各大linux论坛搜寻装GCC的步骤,虽然取得些微的进步,对linux也有一些初步的认识了,但是系统还是不能用。无奈,博主就跑去问老师如何解决linux安装C编译器,不想linux老师来了一句这个red hat他已经不玩好多年了,然后建议我去玩ubuntu。于是,博主就屁颠屁颠地跑去下载最新的ubuntu 10.4,然后安装。出乎意料的是,ubuntu安装要比red hat方便多了,基本属于傻瓜式操作。

所以,接下来博主要讲的基本都是基于ubuntu 10.4平台的。

虽然是新平台,但是ubuntu用的还是linux内核,所以基本和red hat差不多,只有些微差别。

这次操作比上次在red hat上操作顺利多了,博主是参照下文的步骤一步一步实现rpc的:

1.        根据rpc调用的功能,先不考虑rpc调用,编写一个平常的实现相应功能的程序。
如一个远程的文件传输的rpc调用,平常程序便是考虑文件存储在本地,直接打开读便可,如下:
#include <stdio.h>

#include <stdlib.h>

#define MAXNAME 20

#define MAXLENGTH 1024

char * readfile(char *);

int main()

{

    char name[MAXNAME];

    printf("Enter File Name: ");

    scanf("%s", name);

    printf("%s", readfile(name));

}

char * readfile(char * name)

{

    FILE *file = fopen(name, "r");

    char * buf = (char *)malloc(sizeof(char)*MAXLENGTH);

    if (file == NULL)

    {

        printf("File Cann't Be Open!");

        return 0;

    }

    printf("The File Content is : \n");

    while (fgets(buf, MAXLENGTH-1, file) != NULL)

    {

        return buf;

    }

    return NULL;

}

2.        把程序拆分为两部分,main函数和readfile函数,带有main的一部分是主动发起调用的,在rpc中相当于客户端,带有readfile函数的部分是提供相应的功能的,相当于服务器端。将代码拆分后要在客户端添加相应的rpc调用函数,clnt_create(RMACHINE, FILETRANSPROG, FILETRANSVERS,"tcp");

FILETRANSPROG便是trans.x中的程序名,FILETRANSVERS是版本名,使用tcp进行rpc调用。

拆分后代码如下:
客户端client.c:
#include <rpc/rpc.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <unistd.h>

#include "trans.h"

#define WSVERS MAKEWORD(0, 2)

#define RMACHINE "localhost"

CLIENT *handle;

#define MAXNAME 20

#define MAXLENGTH 1024

char * readfile(char *);

int main()

{

    char name[MAXNAME];

    char * buf;

    printf("Enter File Name: ");

    scanf("%s", name);

   handle = clnt_create(RMACHINE, FILETRANSPROG, FILETRANSVERS,"tcp");

   if (handle == 0) {

         printf("Could Not Connect To Remote Server.\n");

         exit(1);

   }

    buf = readfile(name);

    printf("%s", buf);

    return 0;

}

服务器端server.c:
#include <rpc/rpc.h>

#include <stdio.h>

#include <stdlib.h>

#include "trans.h"

#define MAXNAME 20

#define MAXLENGTH 1024

char * readfile(char * name)

{

    FILE *file = fopen(name, "r");

    char * buf = (char *)malloc(sizeof(char)*MAXLENGTH);

    if (file == NULL)

    {

        printf("File Cann't Be Open!");

        return 0;

    }

    printf("The File Content is : \n");

    while (fgets(buf, MAXLENGTH-1, file) != NULL)

    {

        return buf;

    }

    return NULL;

}

3.        编写***.x文件。具体步骤可以参考Douglas的那本Internetworking With TCP/IP 的第三卷,客户端-服务器端编程与应用。
本程序的.x文件命名为trans.x内容如下:
const MAXLENGTH = 1024;

const MAXNAME = 20;

program FILETRANSPROG  //程序名

    version FILETRANSVERS  //版本名
    { 

        string READFILE(string) = 1;  //调用的方法名
    } = 1; 

} = 99;

4.        使用rpcgen编辑.x文件,在linux下输入命令
rpcgen   trans.x

若格式正确,编译无错误则产生三个文件trans.h,trans_svc.c(服务器端),trans_clnt.c(客户端)。因为上述trans.x中无自定义数据结构,所以没有xdr文件产生。
trans.h代码:
/*

 * Please do not edit this file.

 * It was generated using rpcgen.

 */

#ifndef _TRANS_H_RPCGEN

#define _TRANS_H_RPCGEN

#include <rpc/rpc.h>

#ifdef __cplusplus

extern "C" {

#endif

#define MAXLENGTH 1024

#define MAXNAME 20

#define FILETRANSPROG 99

#define FILETRANSVERS 1

#if defined(__STDC__) || defined(__cplusplus)

#define READFILE 1

extern  char ** readfile_1(char **, CLIENT *);

extern  char ** readfile_1_svc(char **, struct svc_req *);

extern int filetransprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);

#else /* K&R C */

#define READFILE 1

extern  char ** readfile_1();

extern  char ** readfile_1_svc();

extern int filetransprog_1_freeresult ();

#endif /* K&R C */

#ifdef __cplusplus

}

#endif

#endif /* !_TRANS_H_RPCGEN */

trans_svc.c代码:
/*

 * Please do not edit this file.

 * It was generated using rpcgen.

 */

#include "trans.h"

#include <stdio.h>

#include <stdlib.h>

#include <rpc/pmap_clnt.h>

#include <string.h>

#include <memory.h>

#include <sys/socket.h>

#include <netinet/in.h>

#ifndef SIG_PF

#define SIG_PF void(*)(int)

#endif

static void

filetransprog_1(struct svc_req *rqstp, register SVCXPRT *transp)

{

   union {

            char *readfile_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 READFILE:

            _xdr_argument = (xdrproc_t) xdr_wrapstring;

            _xdr_result = (xdrproc_t) xdr_wrapstring;

            local = (char *(*)(char *, struct svc_req *)) readfile_1;

            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;

}

int

main (int argc, char **argv)

{

   register SVCXPRT *transp;

   pmap_unset (FILETRANSPROG, FILETRANSVERS);

   transp = svcudp_create(RPC_ANYSOCK);

   if (transp == NULL) {

            fprintf (stderr, "%s", "cannot create udp service.");

            exit(1);

   }

   if (!svc_register(transp, FILETRANSPROG, FILETRANSVERS, filetransprog_1, IPPROTO_UDP)) {

            fprintf (stderr, "%s", "unable to register (FILETRANSPROG, FILETRANSVERS, 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, FILETRANSPROG, FILETRANSVERS, filetransprog_1, IPPROTO_TCP)) {

            fprintf (stderr, "%s", "unable to register (FILETRANSPROG, FILETRANSVERS, tcp).");

            exit(1);

   }

   svc_run ();

   fprintf (stderr, "%s", "svc_run returned");

   exit (1);

   /* NOTREACHED */

}

trans_clnt.c代码:
/*

 * Please do not edit this file.

 * It was generated using rpcgen.

 */

#include <memory.h> /* for memset */

#include "trans.h"

/* Default timeout can be changed using clnt_control() */

static struct timeval TIMEOUT = { 25, 0 };

char **

readfile_1(char **argp, CLIENT *clnt)

{

   static char *clnt_res;

   memset((char *)&clnt_res, 0, sizeof(clnt_res));

   if (clnt_call (clnt, READFILE,

            (xdrproc_t) xdr_wrapstring, (caddr_t) argp,

            (xdrproc_t) xdr_wrapstring, (caddr_t) &clnt_res,

            TIMEOUT) != RPC_SUCCESS) {

            return (NULL);

   }

   return (&clnt_res);

}

5.        编写客户端和服务器端接口。此部分可以说是最麻烦的部分,稍不注意便会出错,同样可以参考Douglas的那本书,但要注意的是他的服务器接口例程代码中的每个函数的第二个参数应该是CLIENT *clnt, 而非struct svc_req * rqstp

为本程序编写的代码如下:
客户端接口文件trans_cif.c:
#include <rpc/rpc.h>

#include <stdio.h>

#include "trans.h"/* Client-side stub interface routines written by programmer */

extern CLIENT * handle;

static char **ret;

char * readfile(char * name)

{

   char ** arg;

   arg = &name;

   ret = readfile_1(arg, handle);

   return ret==NULL ? NULL : *ret;

}

服务器端接口文件trans_sif.c:
#include <rpc/rpc.h>

#include <stdio.h>

#include "trans.h"

char * readfile(char *);

static char * retcode;

char ** readfile_1(char ** w, CLIENT *clnt)

{

   retcode = readfile(*(char**)w);

   return &retcode;

}

6.        编译链接客户端和服务器端程序
不管是客户端还是服务器端,都要链接三个文件,
客户端:程序文件+*** _clnt.c+客户端接口文件。
服务器端:程序文件+*** _svc.c+服务器端接口文件
同时每一段的三个文件都是互相关联的,编译出现错误时,可以根据提示查看三个文件进行debug

命令如下:
gcc -Wall -o trans_client client.c trans_clnt.c trans_cif.c

gcc -Wall -o trans_server server.c trans_svc.c trans_sif.c

7.        启动服务器端和客户端,大功告成。要先运行服务器端程序,再运行客户端程序。命令如下:
./trans_server

./trans_client

client启动后,提示输入要传输的文件名,输入后,server将文件的第一行传回,大功告成!
本文来自CSDN博客,转载请标明出处:

相关阅读 更多 +
排行榜 更多 +
奥丘树海之下小米服手游下载

奥丘树海之下小米服手游下载

角色扮演 下载
网络天才国际服手游下载

网络天才国际服手游下载

休闲益智 下载
御剑红尘手游官方版下载

御剑红尘手游官方版下载

角色扮演 下载