rpc远程调用框架,rpc远程调用原理
1.RPC简介RPC是远程过程调用的缩写。RPC可以用来实现在本地机器上调用远程机器的功能或过程。调用过程如下:
2.外部数据表示(XDR)2.1。简介XDR是数据描述和编码的标准。XDR协议对于不同系统的计算机之间的数据传输非常有用。XDR属于ISO表示层。XDR用语言描述数据结构,只用来描述结构。工作原理:
2.2.XDR相关函数1。初始化XDR流
函数的作用是:初始化一个XDR流。
#包含rpc/types.h
#包含rpc/xdr.h
void xdrstdio_create(XDR *xdrs,FILE *file,enum XDR _ op);在xdrstdio_create函数中,参数fp是指向文件结构的指针。参数op为枚举类型,其值为XDR_ENCODE、XDR_DECODE、XDR_FREE。XDR_ENCODE操作对数据进行编码,并将其输出到流。XDR_DECODE操作会解码流中的数据吗?参数句柄是一个指向XDR结构的指针,它将在将来的操作中使用。
2.释放XDR流
函数xdr_destroy用于释放分配的xdr流,参数handle是指向XDR句柄的指针。
#包含rpc/xdr.h
void XDR _ destroy(XDR * xdrs);3.各种类型数据的XDR转换功能
Handle是通过调用xdrstdio_create生成的,第二个参数是指向要转换的数据的指针。如果转换成功,将返回TRUE否则,它将返回FALSE。
#包含rpc/xdr.h
#包含rpc/types.h
bool_t xdr_int(XDR *xdrs,int * IP);//整数
bool_t xdr_u_int(XDR *xdrs,unsigned * up);//无符号整数
bool_t xdr_short(XDR *xdrs,short * sp);//短整数
bool_t xdr_u_short(XDR *xdrs,无符号short * USP);//无符号短整型
bool_t xdr_long(XDR *xdrs,long * LP);//长整数
bool_t xdr_u_long(XDR *xdrs,无符号long * ulp);//无符号长整数
bool_t xdr_bool(XDR *xdrs,bool _ t * BP);//布尔型
bool_t xdr_enum(XDR *xdrs,enum _ t * EP);//枚举
bool_t xdr_float(XDR *xdrs,float * FP);//单精度浮点类型
bool_t xdr_double(XDR *xdrs,double * DP);//双精度浮点型
bool_t xdr_char(XDR *xdrs,char * CP);//字符类型
bool_t xdr_string(XDR *xdrs,char **sp,unsigned int maxsize);//字符串类型
bool_t xdr_bytes(XDR *xdrs,char **sp,unsigned int *sizep,
无符号int maxsize);//字节流
bool_t xdr_vector(XDR *xdrs,char *arrp,无符号int size,
unsigned int elsize,XDR proc _ t El proc);//固定长度数组
bool_t xdr_array(XDR *xdrs,char **arrp,unsigned int *sizep,
无符号int maxsize,无符号int elsize,
XDR proc _ t El proc);//可变长度数组3。RPC编程3.1。简介RPC程序避开了网络接口的细节,为程序员提供网络服务,而不要求他们知道基本网络的存在和功能。
RPC程序通常包括以下主要部分:
“RPC程序的程序号、版本号和过程号”:RPC程序的程序号、版本号和过程号唯一标识通过RPC调用的过程。
“网络选择”:可以编写在指定传输和传输类型上运行的程序,也可以编写在系统或用户选择的传输上运行的程序。
“rpcbind服务”:rpcbind是用于连接网络服务和网络地址的基本服务。
“外部数据即XDR”:RPC客户端和服务器之间传输的数据按照XDR传输语法进行编码。
程序编号
每个RPC过程都由程序员、版本号和过程号唯一标识。
否。程序规则:
网络选择
网络选择意味着用户和应用程序可以根据自己的需要选择使用的传输协议。主要是udp或者tcp。
Rpcbind服务
rpcbind协议定义了一个网络服务,它为客户端提供了一个标准的方法来查找服务器支持的任何远程程序的传输地址。Rpcbind通常使用端口号111。
3.2.RPC调用客户端首先调用clnt_create生成客户端结构的指针,然后调用函数clnt_call调用远程过程,调用clnt_destroy关闭连接,最后退出应用程序。在服务器端,调用svcudp_create或者svctcp_create生成一个SVCXPRT结构的指针,然后调用svc_register注册提供的服务,最后调用svc_run。当服务器程序退出时,它需要调用svc_destroy来释放连接。
3.3.RPC相关功能1。clnt _创建函数
用于生成指向客户端结构的指针。如果返回NULL,则表明有错误。这个函数的第一个参数是服务器名或IP地址,第二个参数是程序号,第三个参数是版本号,第四个参数是协议类型。
#包含rpc/clnt.h
CLIENT *clnt_create(char *host,无符号long prog,
无符号长vers,char * proto);2.clnt_call函数
是用来调用服务器的一个进程吗?如果函数返回RPC_SUCCESS,说明调用成功,否则会出错。函数的第一个参数是clnt_create生成的客户端结构的指针,第二个参数是过程号,第三个参数是被调用过程的返回类型,第四个参数是传递给过程的参数的地址,第五个参数是编解码函数的名称,第六个参数是编解码函数的地址,最后一个参数是给定的超时值。
#包含rpc/clnt.h
enum clnt _ stat clnt _ call(CLIENT * clnt,无符号long procnum,
xdrproc_t inproc,char *in,
xdrproc_t outproc,char *out,
struct timeval(0,92,197);边距:0px填充:0px背景:none 0% 0%/auto repeat scroll padding-box border-box rgba(0,0,0,0);tout);3.clnt_destroy函数
释放clnt_create返回的指针,关闭连接。
#包含rpc/clnt.h
clnt _ destroy(CLIENT * clnt);4.svcudp_create函数
指向用于生成无连接UDP服务的SVCXPRT结构的指针。如果返回NULL,将会出现错误。该函数唯一的参数是套接字类型,通常是RPC_ANYSOCK。
#包含rpc/svc.h
SVC xprt * svcudp _ create(int sock);5.svctcp_create函数
指向用于生成面向连接的TCP服务的SVCXPRT结构的指针。如果返回NULL,将会出现错误。函数的第一个参数是socket类型,通常是RPC_ANYSOCK。第二个参数是发送缓冲区大小,0代表系统默认值。第三个参数是接收缓冲区大小,0代表系统默认值。
#包含rpc/svc.h
SVCXPRT *svctcp_create(int sock,unsigned int send_buf_size,
无符号int recv _ buf _ size);6.svc_register函数
用于向主机注册服务,成功时返回TRUE,失败时返回FALSE。函数的第一个参数是指向svcudp_create或svctcp_create生成的SVCXPRT结构的指针,第二个参数是程序号,第三个参数是版本号,第四个参数是处理请求的函数名,最后一个参数是协议名。IPPROTO_UDP代表UDP协议,IPPROTO_TCP代表TCP协议。
#包含rpc/svc.h
bool _ t SVC _ register(SVC xprt * xprt,无符号长整型prognum,
无符号long versnum,
void (*dispatch)(svc_req *,SVCXPRT *),
无符号长协议);Svc _运行函数
服务器注册了提供的服务后,调用函数svc_run等待客户端请求的到来,不返回也没有参数。
#包含rpc/svc.h
void SVC _ run(void);7.svc_sendreply函数
当服务器得到客户端请求的结构时,服务器程序需要调用函数svc_sendreply向客户端发送消息。如果函数返回TRUE,则调用成功;如果为FALSE,将会失败。函数的第一个参数是SVCXPRT指针,第二个参数是编解码器函数的名称,第三个参数是结果的地址。
#包含rpc/svc.h
bool _ t SVC _ send reply(SVC xprt * xprt,xdrproc_t outproc,char * out);4.实现远程计算器4.1,公共头文件xdr _ math.h #包含iostream
#包含rpc/types.h
#包含rpc/xdr.h
#包含rpc/clnt.h
#包含rpc/svc.h
结构数学
{
int op
浮点arg1
浮点arg2
浮点结果;
};
bool xdr_math(XDR *xdrsp,struct MATH * resp)
{
如果(!xdr_int(xdrsp,resp- op))
{
返回false
}
如果(!xdr_float(xdrsp,resp- arg1))
{
返回false
}
如果(!xdr_float(xdrsp,resp- arg2))
{
返回false
}
如果(!xdr_float(xdrsp,resp- result))
{
返回false
}
返回TRUE
}
#define MATH_PROG((无符号长整型)0x20000001)
#define MATH_VER((无符号长整型)0x1)
#define MATH_PROC((无符号长整型)0x1)
#定义添加0
#定义子1
#定义MUL 2
#define DIV 34.2,客户端程序math _ client . CPP # include XDR _ math . h
使用命名空间std
无效用法(char * name)
{
cout 用法: name hostname/IP addr \ n ;
出口(1);
}
int main(int argc,char **argv)
{
如果(argc!=2)
{
用法(argv[0]);
}
cout 选择操作:\ n \ t 0-ADD \ t 1-SUB \ t 2-MUL \ t 3-DIV \ n ;
char c;
CIN c;
结构数学数学;
开关(三)
{
案例"0":
math.op=ADD
打破;
案例"1":
数学. op=SUB
打破;
案例"2":
数学运算=乘法运算
打破;
案例"3":
math.op=DIV
打破;
默认值:
“cout”错误:操作\ n ";
出口(1);
}
cout 输入第一个数字:;
CIN数学。arg 1;
cout 输入第二个数:;
CIN数学。arg 2;
CLIENT * CLIENT=clnt _ create(argv[1],MATH_PROG,MATH_VER, TCP );
//CLIENT * CLIENT=clnt _ create(argv[1],MATH_PROG,MATH_VER, UDP );
if(client==NULL)
{
“cout”错误:clnt _ create \ n ";
出口(1);
}
struct timeval(0,92,197);边距:0px填充:0px背景:none 0% 0%/auto repeat scroll padding-box border-box rgba(0,0,0,0);超时;
timeout.tv _ sec=30
暂停。TV _ usec=0;
enum clnt _ stat stat=clnt _ call(client,MATH_PROC,(xdrproc_t)xdr_math,(char *) math,(xdrproc_t)xdr_math,(char *) math,超时);
如果(统计!=RPC_SUCCESS)
{
clnt_perror(客户端,调用失败);
出口(1);
}
cout 结果是数学.结果 .\ n ;
clnt_destroy(客户端);
返回0;
}4.3、服务器程序数学_服务器。CPP #包含 XDR _ math。 h
使用命名空间标准
静态void数学程序(struct SVC _ req * rqstp,SVCXPRT *transp)
{
开关(rqstp- rq_proc)
{
case NULLPROC:
svc_sendreply(transp,(xdrproc_t)xdr_void,NULL);
返回;
案例数学_过程:
打破;
默认值:
SVC err _ no proc(transp);
返回;
}
结构数学数学;
memset((char *) math,0,sizeof(math));
如果(!svc_getargs(transp,(xdrproc_t)xdr_math,(caddr_t) math))
{
SVC err _ decode(transp);
返回;
}
开关(数学运算)
{
案例添加:
数学。成绩=数学。arg 1数学。arg 2;
打破;
案例子案例:
数学。成绩=数学。arg 1-数学。arg 2;
打破;
案例MUL:
数学。成绩=数学。arg 1 *数学。arg 2;
打破;
案例部门:
数学。成绩=数学。arg 1/数学。arg 2;
打破;
默认值:
打破;
}
如果(!svc_sendreply(transp,(xdrproc_t)xdr_math,(caddr_t) math))
{
“cout”错误:无法发送回复\ n ";
出口(1);
}
如果(!svc_freeargs(transp,(xdrproc_t)xdr_math,(caddr_t) math))
{
“cout”错误:无法释放参数\ n ";
出口(1);
}
返回;
}
int main(int argc,char **argv)
{
SVC xprt * transpu=svcudp _ create(RPC _ any sock);
if(transpu==NULL)
{
“cout”错误:无法创建用户数据报协议服务. \ n ;
出口(1);
}
如果(!svc_register(transpu,MATH_PROG,MATH_VER,mathprog,IPPROTO_UDP))
{
“cout”错误:无法注册(MATH_PROG udp).\ n ;
出口(1);
}
SVC xprt * transpt=svctcp _ create(RPC _ any sock,0,0);
if(transpt==NULL)
{
“cout”错误:无法创建传输控制协议服务. \ n ;
出口(1);
}
如果(!svc_register(transpt,MATH_PROG,MATH_VER,mathprog,IPPROTO_TCP))
{
“cout”错误:无法注册(ADDPROG tdp).\ n ;
出口(1);
}
SVC _ run();
cout "错误:scv_run已返回";
出口(1);
}4.4、编译g -o数学客户端数学客户端
g-o数学服务器数学服务器。CPP-lnsl 4.5、执行启动rpcbind
服务rpcbind启动启动服务器程序。/math_server启动客户端程序。/数学_客户端本地主机
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。