WEB开发网
开发学院软件开发Shell Sun RPC 编程简介 阅读

Sun RPC 编程简介

 2009-06-30 04:59:00 来源:WEB开发网   
核心提示:一、 概述在传统的编程概念中,过程是由程序员在本地编译完成,Sun RPC 编程简介,并只能局限在本地运行的一段代码,也即其主程序和过程之间的运行关系是本地调用关系,d) 一个Client 端的标准程序框架,当然,因此这种结构在网络日益发展的今天已无法适应实际需求,总所周知

  一、 概述
  在传统的编程概念中,过程是由程序员在本地编译完成,并只能局限在本地运行的一段代码,也即其主程序和过程之间的运行关系是本地调用关系。因此这种结构在网络日益发展的今天已无法适应实际需求。总所周知,传统过程调用模式无法充分利用网络上其他主机的资源(如CPU、Memory等),也无法提高代码在实体间的共享程度,使得主机资源大量浪费。
  而本文要介绍的RPC编程,正是很好地解决了传统过程所存在的一系列弊端。通过RPC我们可以充分利用非共享内存的多处理器环境(例如通过局域汪连接得多台工作站),这样可以简便地将你的应用分布在多台工作站上,应用程序就像运行在一个多处理器的计算机上一样。你可以方便的实现过程代码共享,提高系统资源的利用率,也可以将以大量数值处理的操作放在处理能力较强的系统上运行,从而减轻前端机的负担。
  
  二、 RPC的结构原理及其调用机制
  如前所述RPC其实也是种C/S的编程模式,有点类似C/S Socket 编程模式,但要比它更高一层。当我们在建立RPC服务以后,客户端的调用参数通过底层的RPC传输通道,可以是UDP,也可以是TCP(也即TI-RPC-无关性传输),并根据传输前所提供的目的地址及RPC上层应用程序号转至相应的RPC Application Porgramme Server ,且此时的客户端处于等待状态,直至收到应答或Time Out超时信号。具体的流程图如F1。当服务器端获得了请求消息,则会根据注册RPC时告诉RPC系统的例程入口地址,执行相应的操作,并将结果返回至客户端。
  
  F1
  当一次RPC调用结束后,相应线程发送相应的信号,客户端程序才会继续运行。当然,一台服务主机上可以有多个远程过程提供服务,那么如何来表示一个唯一存在的远程过程呢?一个远程过程是有三个要素来唯一确定的:程序号、版本号和过程号。程序号是用来区别一组相关的并且具有唯一过程好的远程过程。一个程序可以有一个或几个不同的版本,而每个版本的程序都包含一系列能被远程调用的过程,通过版本的引入,使得不同版本下的RPC能同时提供服务。每个版本都包含有许多可供远程调用的过程,每个过程则有其唯一标示的过程号。
  
  三、 基于RPC的应用系统开发
  通过以上对RPC原理的简介后,我们再来继续讨论如何来开发基于RPC的应用系统。
  一般而言在开发RPC时,我们通常分为三个步骤:
  a、 定义说明客户/服务器的通信协议。
  这里所说的通信协议是指定义服务过程的名称、调用参数的数据类型和返回参数的数据类型,还包括底层传输类型(可以是UDP或TCP),当然也可以由RPC底层函数自动选择连接类型建立TI-RPC。最简单的协议生成的方法是采用协议编译工具,常用的有Rpcgen, 我会在后面实例中详细描述其使用方法。
  b、 开发客户端程序。
  c、 开发服务器端程序。
  开发客户端和服务器端的程序时,RPC提供了我们不同层次的开发例程调用接口。不同层次的接口提供了对RPC不同程度控制。一般可分为5个等级的编程接口,接下来我们分别讨论一下各层所提供的功能函数。
  1、 简单层例程
  简单层是面向普通RPC应用,为了快速开发RPC应用服务而设计的,他提供了如下功能函数。
  函数名       功能描述
  Rpc_reg( ) 在一特定类型的传输层上注册某个过程,来作为提供服务的RPC程序
  Rpc_call( ) 远程调用在指定主机上指定的过程
  Rpc_Broadcast( ) 向指定类型的所有传输端口上广播一个远程过程调用请求
  
  2、 高层例程
  在这一层,程序需要在发出调用请求前先创建一个客户端句柄,或是在侦听请求前先建立一个服务器端句柄。程序在该层可以自由的将自己的应用绑在所有的传输端口上,它提供了如下功能函数。
  
  函数名       功能描述
  Clnt_create( ) 程序通过这个功能调用,告诉底层RPC服务器的位置及其传输类型
  Clnt_create_timed( ) 定义每次尝试连接的超时最大时间
  Svc_create( ) 在指定类型的传输端口上建立服务器句柄,告诉底层RPC事件过程的相应入口地址
  Clnt_call() 向服务器端发出一个RPC调用请求
  
  3、 中间层例程
  中间层向程序提供更为详细的RPC控制接口,而这一层的代码变得更为复杂,但运行也更为有效,它提供了如下功能函数。
  函数名       功能描述
  Clnt_tp_create( ) 在指定的传输端口上建立客户端句柄
  Clnt_tp_create_timed( ) 定义最大传输时延
  Svc_tp_creaet( ) 在指定的传输端口上建立服务句柄
  Clnt_call( ) 向服务器端发出RPC调用请求
  
  4、 专家层例程
  这层提供了更多的一系列与传输相关的功能调用,它提供了如下功能函数。
  
  函数名       功能描述
  Clnt_tli_create( ) 在指定的传输端口上建立客户端句柄
  Svc_tli_create( ) 在指定的传输端口上建立服务句柄
  Rpcb_set( ) 通过调用rpcbind将RPC服务和网络地址做映射
  Rpcb_unset( ) 删除rpcb_set( ) 所建的映射关系
  Rpcb_getaddr( ) 调用rpcbind来犯会指定RPC服务所对应的传输地址
  Svc_reg( ) 将指定的程序和版本号与相应的时间例程建起关联
  Svc_ureg( ) 删除有svc_reg( ) 所建的关联
  Clnt_call( ) 客户端向指定的服务器端发起RPC请求
  
  5、 底层例程
  该层提供了所有对传输选项进行控制的调用接口,它提供了如下功能函数。
  
  函数名       功能描述
  Clnt_dg_create( ) 采用无连接方式向远程过程在客户端建立客户句柄
  Svc_dg_create( ) 采用无连接方式建立服务句柄
  Clnt_vc_create( ) 采用面向连接的方式建立客户句柄
  Svc_vc_create( ) 采用面向连接的方式建立RPC服务句柄
  Clnt_call( ) 客户端向服务器端发送调用请求
  
  四、 实例介绍
  以下我将通过实例向读者介绍通过简单层RPC的实现方法。通常在此过程中我们将使用RPC协议编译工具-Rpcgen。Rpcgen 工具用来生成远程程序接口模块,它将以RPC语言书写的源代码进行编译,Rpc 语言在结构和语法上同C语言相似。由Rpcgen 编译生成的C源程序可以直接用C编译器进行编译,因此整个编译工作将分为两个部分。Rpcgen的源程序以.x结尾,通过其编译将生成如下文件:
  a) 一个头文件(.h)包括服务器和客户端程序变量、常量、类型等说明。
  b) 一系列的XDR例程,它可以对头文件中定义的数据类型进行处理。
  c) 一个Server 端的标准程序框架。
  d) 一个Client 端的标准程序框架。
  当然,这些输出可以是选择性的,Rpcgen 的编译选项说明如下:
  选项 功能
  '-' a 生成所有的模板文件
  '-' Sc 生成客户端的模板文件
  '-' Ss 生成服务器端的模板文件
  '-' Sm 生成Makefile 文件
  (详见Solaris Rpcgen Manaul)
  
  Rpcgen 源程序 time.x:
  /* time.x: Remote time printing protocol */
  program TIMEPROG {
  version PRINTIMEVERS {
  string PRINTIME(string) = 1;
  } = 1;
  } = 0x20000001;
  time_proc.c源程序:
  /* time_proc.c: implementation of the remote procedure "printime" */
  #include <stdio.h>
  #include <rpc/rpc.h>      /* always needed */
  #include "time.h" /* time.h will be generated by rpcgen */
  #include <time.h>
  /* Remote version of "printime" */
  char ** printime_1(char **msg,struct svc_req *req)
  
  {
  static char * result; /* must be static! */
  static char tmp_char[100];
  time_t rawtime;
  
  FILE *f;
  
  f = fopen("/tmp/rpc_result", "a+");
  if (f == (FILE *)NULL) {
  strcpy(tmp_char,"Error");
  result = tmp_char;;
  return (&result);
  }
  fprintf(f, "%s\n", *msg); //used for debugging
  fclose(f);
  time(&rawtime);
  sprintf(tmp_char,"Current time is :%s",ctime(&rawtime));
  result =tmp_char;
  return (&result);
  }
  rtime.c源代码
  /*
  * rtime.c: remote version
  * of "printime.c"
  */
  
  #include <stdio.h>
  #include "time.h" /* time.h generated by rpcgen */
  
  main(int argc, char **argv)
  
  {
  CLIENT *clnt;
  char *result;
  char *server;
  char *message;
  
  
  if (argc != 3) {
  fprintf(stderr, "usage: %s host message\n", argv[0]);
  exit(1);
  }
  
  server = argv[1];
  message = argv[2];
  
  /*
  * Create client "handle" used for
  * calling TIMEPROG on the server
  * designated on the command line.
  */
  
  clnt = clnt_create(server, TIMEPROG, PRINTIMEVERS, "visible");
  
  if (clnt == (CLIENT *)NULL) {
  /*
  * Couldn't establish connection
  * with server.
  * Print error message and die.
  */
  
  clnt_pcreateerror(server);
  exit(1);
  }
  
  /*
  
  * Call the remote procedure
  * "printime" on the server
  */
  
  result =*printime_1(&message,clnt);
  if

Tags:Sun RPC 编程

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接