【转载】 Sun RPC 编程简介
原文地址:
http://blog.chinaunix.net/uid-1724205-id-2813082.html
=============================================================
一、 概述
在传统的编程概念中,过程是由程序员在本地编译完成,并只能局限在本地运行的一段代码,也即其主程序和过程之间的运行关系是本地调用关系。因此这种结构在网络日益发展的今天已无法适应实际需求。总所周知,传统过程调用模式无法充分利用网络上其他主机的资源(如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 (result== (char *)NULL) {
/*
* An error occurred while calling
* the server.
* Print error message and die.
*/ clnt_perror(clnt, server);
exit(1);
} /* Okay, we successfully called
* the remote procedure.
*/ if (strcmp(result,"Error") == 0) { /*
* Server was unable to print
* the time.
* Print error message and die.
*/ fprintf(stderr, "%s: could not get the time\n",argv[0]);
exit(1);
}
printf("From the Time Server ...%s\n",result);
clnt_destroy( clnt );
exit(0);
}
有了以上的三段代码后,就可用rpcgen 编译工具进行RPC协议编译,命令如下:
$rpcgen time.x
rpcgen 会自动生成time.h、time_svc.c、time_clnt.c
再用系统提供的gcc进行C的编译,命令如下:
$gcc rtime.c time_clnt.c -o rtime -lnsl //客户端编译
$gcc time_proc.c time_svc.c -o time_server -lnsl //服务器端编译
编译成功后即可在Server端运行time_server,立即将该服务绑定在rpc服务端口上提供
服务。在客户端运行./rdate hostname msg (msg 是一字符串,笔者用来测试时建立的),
立即会返回hostname 端的时间。
由于,在Sun Solaris 中无法获取远端Server 上时钟信息的功能(不改变本
地Server时钟),笔者曾将此程序应用于计费服务器同时钟服务器同步监测的网管
系统中,运行稳定,获得了较好的效果。应该说RPC的应用是十分广泛的,特别是
在分布式计算领域中尤为显得重要。当然,笔者也是刚接触RPC,还有很多地方了
解的不够深刻,望广大读者多指教。
【转载】 Sun RPC 编程简介的更多相关文章
- 转载:JavaScript多线程编程简介
虽然有越来越多的网站在应用AJAX技术进行开发,但是构建一个复杂的AJAX应用仍然是一个难题.造成这些困难的主要原因是什么呢?是与服务器的异步通信问题?还是GUI程序设计问题呢?通常这两项工作都是由桌 ...
- SOCKet 编程 简介
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。
RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大.最高效的方法之一.它为在分布式计算环境中运行的几乎所有应用程序提供基础.本文介绍 RPC 客户机和服务器之间基本的事件流 ...
- 《编程简介(Java) ·10.3递归思想》
<编程简介(Java) ·10.3递归思想> 10.3.1 递归的概念 以两种方式的人:男人和女人:算法是两种:递归迭代/通知: 递归方法用自己的较简单的情形定义自己. 在数学和计算机科学 ...
- 《转载》RPC入门总结(一)RPC定义和原理
转载:深入浅出 RPC - 浅出篇 转载:RPC框架与Dubbo完整使用 转载:深入浅出 RPC - 深入篇 转载:远程调用服务(RPC)和消息队列(Message Queue)对比及其适用/不适用场 ...
- OpenCL学习笔记(三):OpenCL安装,编程简介与helloworld
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. OpenCL安装 安装我不打算 ...
- 【在 Nervos CKB 上做开发】Nervos CKB脚本编程简介[2]:脚本基础
CKB脚本编程简介[2]:脚本基础 原文作者:Xuejie 原文链接:Introduction to CKB Script Programming 2: Script 本文译者:Shooter,Jas ...
- UNIX网络编程---简介
UNIX网络编程---简介 一. 概述 a) 在编写与计算机通信的程序时,首先要确定的就是和计算机通信的协议,从高层次来确定通信由哪个程序发起以及响应在合适产生.大多数 ...
- win32编程简介
win32编程简介 复习Win32整理下知识. 为什么学习win32? 我们要编写windos程序.都离不开API. 也就是我们所说的win32程序. 所以学好win32是你能不能再windows下编 ...
- 【Unix网络编程】chapter3套接字编程简介
chapter3套接字编程简介3.1 概述 地址转换函数在地址的文本表达和他们存放在套接字地址结构中的二进制值之间进行转换.多数现存的IPv4代码使用inet_addr和inet_ntoa这两个函数, ...
随机推荐
- 流程控制之case
1.case语句作用 case和if一样,都是用于处理多分支的条件判断 但是在条件较多的情况,if嵌套太多就不够简洁了 case语句就更简洁和规范了 2.case用法参考 常见用法就是如根据用户输入的 ...
- LNMP集群架构
网站集群拆分 上一节我们是部署了单机的LNMP,再往下,要进行拆分了,无论是性能.还是安全性,都务必要拆分. 拆分的内容有 nginx集群 mysql nfs共享存储 等 拆分思路 情况1 当前的单机 ...
- HTTP长连接、短连接、Linux网络优化
无连接 含义:每次传输完数据后就断开连接. 因为早期互联网规模小,并且http具有瞬时性,突发性,服务器同时处理着多个请求.所以采用无连接的方式.以便于腾出资源处理其他请求. 无状态 顺便说一说无状态 ...
- 异构智联Wi-Fi6+蓝牙模组,重新定义多屏互联体验!
下班回家打开门,电灯.电视.空调.音响.电动窗帘.扫地机器人--一呼百应,有序开工,原本冰冷的房子立刻变成了温暖港湾.可以说,舒适便捷的智能设备已经完全融入了我们的生活中. 从单一场景.单一设备,到现 ...
- 高通Android平台 电池 相关配置
背景 在新基线上移植有关的代码时,在log中发现有关的东西,请教了有关的同事以后,解决了这个问题. [ 12.775863] pmi632_charger: smblib_eval_chg_termi ...
- C#去除时间格式化之后中间的T字母
需求是这样的, 前后端传参,然后后端序列化把字符串存在数据库. 然后发现时间类型的字段,序列化之后 ,有个字母T, DateTime dt = DateTime.Parse("2024-05 ...
- 题解:洛谷 P1165 日志分析
标签:栈,模拟 题意 对于一个栈,给定三种操作: 0 x,将 \(x\) 入栈: 1,出栈,栈空时忽略: 2,查询当前栈内最大值. 思路 前两个都是栈的基本操作,关键在于查最大值. 每次询问暴力找肯定 ...
- NXP i.MX 6ULL工业开发板规格书( ARM Cortex-A7,主频792MHz)
1 评估板简介 创龙科技TLIMX6U-EVM是一款基于NXP i.MX 6ULL的ARM Cortex-A7高性能低功耗处理器设计的评估板,由核心板和评估底板组成.核心板经过专业的PCB Layou ...
- 【价格全面下调】一片含税79元,双核A7@1.2GHz,-40℃~85℃真工业级!
自9个月前,创龙科技全志T113-i核心板(SOM-TLT113)推出之后,受到广大工业用户的高度关注,且超过300家企业已选用创龙科技T113-i核心板用于终端产品开发. 为了让更多用户轻松选择T1 ...
- 写给rust初学者的教程(二):所有权、生存期
这系列RUST教程一共三篇.这是第二篇,介绍RUST语言的关键概念,主要是所有权和生存期等. 第一篇:写给rust初学者的教程(一):枚举.特征.实现.模式匹配 在写第一篇中的练习代码时,不知道你有没 ...