<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[[rpc 学习]写点rpc的学习（RPC 编程简介）。。。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Fri, 23 Nov 2007 10:01:40 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	　　摘要： <br/>　　本文简单介绍了RPC（Remote Procedure Call 远程过程调用）的原理结构、特点， <br/>　　及其开放给编程人员不同层次的编程接口。并且例举实例示度绾瓮ü齊pcgen 编译工 <br/>　　具来快速开发RPC应用。 <br/>　　一、 概述 <br/>　　在传统的编程概念中，过程是由程序员在本地编译完成，并只能局限在本地运行的一段 <br/>　　代码，也即其主程序和过程之间的运行关系是本地调用关系。因此这种结构在网络日益 <br/>　　发展的今天已无法适应实际需求。总所周知，传统过程调用模式无法充分利用网络上其 <br/>　　他主机的资源（如CPU、Memory等），也无法提高代码在实体间的共享程度，使得主机资 <br/>　　源大量浪费。 <br/>　　而本文要介绍的RPC编程，正是很好地解决了传统过程所存在的一系列弊端。通过RPC我 <br/>　　们可以充分利用非共享内存的多处理器环境（例如通过局域汪连接得多台工作站）,这样 <br/>　　可以简便地将你的应用分布在多台工作站上，应用程序就像运行在一个多处理器的计算机 <br/>　　上一样。你可以方便的实现过程代码共享，提高系统资源的利用率，也可以将以大量数值 <br/>　　处理的操作放在处理能力较强的系统上运行，从而减轻前端机的负担。 <br/>　　二、 RPC的结构原理及其调用机制 <br/>　　如前所述RPC其实也是种C/S的编程模式，有点类似C/S Socket 编程模式，但要比它 <br/>　　更高一层。当我们在建立RPC服务以后，客户端的调用参数通过底层的RPC传输通道，可以 <br/>　　是UDP，也可以是TCP（也即TI-RPC-无关性传输），并根据传输前所提供的目的地址及RPC <br/>　　上层应用程序号转至相应的RPC Application Porgramme Server ，且此时的客户端处于等 <br/>　　待状态，直至收到应答或Time Out超时信号。具体的流程图如F1。当服务器端获得了请求 <br/>　　消息，则会根据注册RPC时告诉RPC系统的例程入口地址，执行相应的操作，并将结果返回 <br/>　　至客户端。 <br/>　　F1 <br/>　　当一次RPC调用结束后，相应线程发送相应的信号，客户端程序才会继续运行。 <br/>　　当然，一台服务主机上可以有多个远程过程提供服务，那么如何来表示一个唯一存 <br/>　　在的远程过程呢？一个远程过程是有三个要素来唯一确定的：程序号、版本号和过程号。 <br/>　　程序号是用来区别一组相关的并且具有唯一过程好的远程过程。一个程序可以有一个或几 <br/>　　个不同的版本，而每个版本的程序都包含一系列能被远程调用的过程，通过版本的引入， <br/>　　使得不同版本下的RPC能同时提供服务。每个版本都包含有许多可供远程调用的过程，每个 <br/>　　过程则有其唯一标示的过程号。 <br/>　　三、 基于RPC的应用系统开发 <br/>　　通过以上对RPC原理的简介后，我们再来继续讨论如何来开发基于RPC的应用系统。 <br/>　　一般而言在开发RPC时，我们通常分为三个步骤： <br/>　　a、 定义说明客户/服务器的通信协议。 <br/>　　这里所说的通信协议是指定义服务过程的名称、调用参数的数据类型和返回参数的数据 <br/>　　类型，还包括底层传输类型（可以是UDP或TCP），当然也可以由RPC底层函数自动选择 <br/>　　连接类型建立TI-RPC。最简单的协议生成的方法是采用协议编译工具，常用的有Rpcgen， <br/>　　我会在后面实例中详细描述其使用方法。 <br/>　　b、 开发客户端程序。 <br/>　　c、 开发服务器端程序。 <br/>　　开发客户端和服务器端的程序时，RPC提供了我们不同层次的开发例程调用接口。不 <br/>　　同层次的接口提供了对RPC不同程度控制。一般可分为5个等级的编程接口，接下来我们 <br/>　　分别讨论一下各层所提供的功能函数。 <br/>　　1、 简单层例程 <br/>　　简单层是面向普通RPC应用，为了快速开发RPC应用服务而设计的，他提供 <br/>　　了如下功能函数。 <br/>　　函数名 功能描述 <br/>　　Rpc_reg( ) 在一特定类型的传输层上注册某个过程，来作为提供服务的RPC程序 <br/>　　Rpc_call( ) 远程调用在指定主机上指定的过程 <br/>　　Rpc_Broadcast( ) 向指定类型的所有传输端口上广播一个远程过程调用请求 <br/>　　2、 高层例程 <br/>　　在这一层，程序需要在发出调用请求前先创建一个客户端句柄，或是在侦听请 <br/>　　求前先建立一个服务器端句柄。程序在该层可以自由的将自己的应用绑在所有的 <br/>　　传输端口上，它提供了如下功能函数。 <br/>　　函数名 功能描述 <br/>　　Clnt_create( ) 程序通过这个功能调用，告诉底层RPC服务器的位置及其传输类型 <br/>　　Clnt_create_timed( ) 定义每次尝试连接的超时最大时间 <br/>　　Svc_create( ) 在指定类型的传输端口上建立服务器句柄，告诉底层RPC事件过程的相应入口地址 <br/>　　Clnt_call() 向服务器端发出一个RPC调用请求 <br/>　　3、 中间层例程 <br/>　　中间层向程序提供更为详细的RPC控制接口,而这一层的代码变得更为复杂， <br/>　　但运行也更为有效，它提供了如下功能函数。 <br/>　　函数名 功能描述 <br/>　　Clnt_tp_create( ) 在指定的传输端口上建立客户端句柄 <br/>　　Clnt_tp_create_timed( ) 定义最大传输时延 <br/>　　Svc_tp_creaet( ) 在指定的传输端口上建立服务句柄 <br/>　　Clnt_call( ) 向服务器端发出RPC调用请求 <br/>　　4、 专家层例程 <br/>　　这层提供了更多的一系列与传输相关的功能调用，它提供了如下功能函数。 <br/>　　函数名 功能描述 <br/>　　Clnt_tli_create( ) 在指定的传输端口上建立客户端句柄 <br/>　　Svc_tli_create( ) 在指定的传输端口上建立服务句柄 <br/>　　Rpcb_set( ) 通过调用rpcbind将RPC服务和网络地址做映射 <br/>　　Rpcb_unset( ) 删除rpcb_set( ) 所建的映射关系 <br/>　　Rpcb_getaddr( ) 调用rpcbind来犯会指定RPC服务所对应的传输地址 <br/>　　Svc_reg( ) 将指定的程序和版本号与相应的时间例程建起关联 <br/>　　Svc_ureg( ) 删除有svc_reg( ) 所建的关联 <br/>　　Clnt_call( ) 客户端向指定的服务器端发起RPC请求 <br/>　　5、 底层例程 <br/>　　该层提供了所有对传输选项进行控制的调用接口，它提供了如下功能函数。 <br/>　　函数名 功能描述 <br/>　　Clnt_dg_create( ) 采用无连接方式向远程过程在客户端建立客户句柄 <br/>　　Svc_dg_create( ) 采用无连接方式建立服务句柄 <br/>　　Clnt_vc_create( ) 采用面向连接的方式建立客户句柄 <br/>　　Svc_vc_create( ) 采用面向连接的方式建立RPC服务句柄 <br/>　　Clnt_call( ) 客户端向服务器端发送调用请求 <br/>　　四、 实例介绍 <br/>　　以下我将通过实例向读者介绍通过简单层RPC的实现方法。通常在此过程中我们 <br/>　　将使用RPC协议编译工具-Rpcgen。Rpcgen 工具用来生成远程程序接口模块，它将以RPC <br/>　　语言书写的源代码进行编译，Rpc 语言在结构和语法上同C语言相似。由Rpcgen 编译生 <br/>　　成的C源程序可以直接用C编译器进行编译，因此整个编译工作将分为两个部分。Rpcgen <br/>　　的源程序以.x结尾，通过其编译将生成如下文件： <br/>　　a) 一个头文件（.h）包括服务器和客户端程序变量、常量、类型等说明。 <br/>　　b) 一系列的XDR例程，它可以对头文件中定义的数据类型进行处理。 <br/>　　c) 一个Server 端的标准程序框架。 <br/>　　d) 一个Client 端的标准程序框架。 <br/>　　当然，这些输出可以是选择性的，Rpcgen 的编译选项说明如下： <br/>　　选项 功能 <br/>　　&#039;-&#039; a 生成所有的模板文件 <br/>　　&#039;-&#039; Sc 生成客户端的模板文件 <br/>　　&#039;-&#039; Ss 生成服务器端的模板文件 <br/>　　&#039;-&#039; Sm 生成Makefile 文件 <br/>　　(详见Solaris Rpcgen Manaul) <br/>　　Rpcgen 源程序 time.x: <br/>　　/* time.x: Remote time printing protocol */ <br/>　　program TIMEPROG { <br/>　　version PRINTIMEVERS { <br/>　　string PRINTIME(string) = 1; <br/>　　} = 1; <br/>　　} = 0x20000001; <br/>　　time_proc.c源程序(服务端)： <br/>　　/* time_proc.c: implementation of the remote procedure &quot;printime&quot; */ <br/>　　#include &lt;stdio.h&gt; <br/>　　#include &lt;rpc/rpc.h&gt; /* always needed */ <br/>　　#include &quot;time.h&quot; /* time.h will be generated by rpcgen */ <br/>　　#include &lt;time.h&gt; <br/>　　/* Remote version of &quot;printime&quot; */ <br/>　　char ** printime_1(char **msg,struct svc_req *req) <br/>　　{ <br/>　　static char * result; /* must be static! */ <br/>　　static char tmp_char[100]; <br/>　　time_t rawtime; <br/>　　FILE *f; <br/>　　f = fopen(&quot;/tmp/rpc_result&quot;, &quot;a+&quot;); <br/>　　if (f == (FILE *)NULL) { <br/>　　strcpy(tmp_char,&quot;Error&quot;); <br/>　　result = tmp_char;; <br/>　　return (&amp;result); <br/>　　} <br/>　　fprintf(f, &quot;%s&#92;n&quot;, *msg); //used for debugging <br/>　　fclose(f); <br/>　　time(&amp;rawtime); <br/>　　sprintf(tmp_char,&quot;Current time is :%s&quot;,ctime(&amp;rawtime)); <br/>　　result =tmp_char; <br/>　　return (&amp;result); <br/>　　} <br/>　　rtime.c源代码 （客户端）<br/>　　/* <br/>　　* rtime.c: remote version <br/>　　* of &quot;printime.c&quot; <br/>　　*/ <br/>　　#include &lt;stdio.h&gt; <br/>　　#include &quot;time.h&quot; /* time.h generated by rpcgen */ <br/>　　main(int argc, char **argv) <br/>　　{ <br/>　　CLIENT *clnt; <br/>　　char *result; <br/>　　char *server; <br/>　　char *message; <br/>　　if (argc != 3) { <br/>　　fprintf(stderr, &quot;usage: %s host message&#92;n&quot;, argv[0]); <br/>　　exit(1); <br/>　　} <br/>　　server = argv[1]; <br/>　　message = argv[2]; <br/>　　/* <br/>　　* Create client &quot;handle&quot; used for <br/>　　* calling TIMEPROG on the server <br/>　　* designated on the command line. <br/>　　*/ <br/>　　clnt = clnt_create(server, TIMEPROG, PRINTIMEVERS, &quot;visible&quot;); <br/>　　if (clnt == (CLIENT *)NULL) { <br/>　　/* <br/>　　* Couldn&#039;t establish connection <br/>　　* with server. <br/>　　* Print error message and die. <br/>　　*/ <br/>　　clnt_pcreateerror(server); <br/>　　exit(1); <br/>　　} <br/>　　/* <br/>　　* Call the remote procedure <br/>　　* &quot;printime&quot; on the server <br/>　　*/ <br/>　　result =*printime_1(&amp;message,clnt); <br/>　　if (result== (char *)NULL) { <br/>　　/* <br/>　　* An error occurred while calling <br/>　　* the server. <br/>　　* Print error message and die. <br/>　　*/ <br/>　　clnt_perror(clnt, server); <br/>　　exit(1); <br/>　　} <br/>　　/* Okay, we successfully called <br/>　　* the remote procedure. <br/>　　*/ <br/>　　if (strcmp(result,&quot;Error&quot;) == 0) { <br/>　　/* <br/>　　* Server was unable to print <br/>　　* the time. <br/>　　* Print error message and die. <br/>　　*/ <br/>　　fprintf(stderr, &quot;%s: could not get the time&#92;n&quot;,argv[0]); <br/>　　exit(1); <br/>　　} <br/>　　printf(&quot;From the Time Server ...%s&#92;n&quot;,result); <br/>　　clnt_destroy( clnt ); <br/>　　exit(0); <br/>　　} <br/>　　有了以上的三段代码后，就可用rpcgen 编译工具进行RPC协议编译，命令如下： <br/>　　$rpcgen time.x <br/>　　rpcgen 会自动生成time.h、time_svc.c、time_clnt.c <br/>　　再用系统提供的gcc进行C的编译，命令如下： <br/>　　$gcc rtime.c time_clnt.c -o rtime -lnsl //客户端编译 在freebsd下不要用-lnsl<br/>　　$gcc time_proc.c time_svc.c -o time_server -lnsl //服务器端编译 &nbsp;在freebsd下不要用-lnsl<br/>　　编译成功后即可在Server端运行time_server，立即将该服务绑定在rpc服务端口上提供 <br/>　　服务。在客户端运行./rtime &nbsp;hostname msg (msg 是一字符串，笔者用来测试时建立的)， <br/>　　立即会返回hostname 端的时间。 <br/>　　由于，在Sun Solaris 中无法获取远端Server 上时钟信息的功能（不改变本 <br/>　　地Server时钟），笔者曾将此程序应用于计费服务器同时钟服务器同步监测的网管 <br/>　　系统中，运行稳定，获得了较好的效果。应该说RPC的应用是十分广泛的，特别是 <br/>　　在分布式计算领域中尤为显得重要。当然，笔者也是刚接触RPC，还有很多地方了 <br/>　　解的不够深刻，望广大读者多指教。 <br/><br/>
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [rpc 学习]写点rpc的学习（RPC 编程简介）。。。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>