TI-RPC客户端、服务端接口实例

TI-RPC客户端服务端接口实例,cygwin libtirpc,

  • 如何传递参数和结果?
  • 绑定如何进行?
  • 传输协议如何处理?
  • 调用语义是什么?
  • 使用什么数据表示形式?

参数传递
TI-RPC允许将单个参数从客户端传递到服务器。如果需要多个参数,则可以将这些组件组合成一个被视为单个元素的结构。从服务器传递到客户端的信息作为函数的返回值传递。无法通过参数列表将信息从服务器传递回客户端。

捆绑
客户必须知道如何联系服务。两个必要的方面是找出服务器所在的主机,然后连接到实际的服务器进程。在每个主机上,一个名为rpcbind的服务管理RPC服务。TI-RPC使用可用的主机命名服务(例如主机文件,NIS +和DNS)来查找主机。

传输协议
传输协议指定如何在客户端和服务器之间传输呼叫消息和回复消息。TS-RPC使用TCP和UDP作为传输协议,但是TI-RPC的当前版本与传输无关,因此可以与任何传输协议一起使用。

呼叫语义
调用语义定义了客户端可以对远程过程的执行承担什么;特别是该过程执行了多少次。这些语义对于处理错误条件很重要。这三种选择分别是一次,最多一次和 至少一次。ONC +提供至少一次语义。远程调用的过程是幂等的:每次调用它们都应返回相同的结果,即使经过多次迭代也是如此。

数据表示
数据表示形式描述了参数和结果在流程之间传递时所使用的格式。为了在各种系统体系结构上起作用,RPC需要标准的数据表示形式。TI-RPC使用外部数据表示(XDR)。XDR是与机器无关的数据描述和编码协议。使用XDR,RPC可以处理任意数据结构,而不管不同主机的字节顺序或结构布局约定如何。有关XDR的详细讨论,请参见附录A,XDR技术说明和附录C,XDR协议规范。

————————————-

程序,版本和过程编号

远程过程由三元组唯一标识:

  • 程序编号
  • 版本号
  • 程序编号

节目号标识一组相关的远程程序,其中的每一个都有一个唯一的过程号。

一个程序可以包含一个或多个版本。每个版本都包含一组可远程调用的过程。版本号使RPC协议的多个版本可以同时可用。

每个版本都包含许多可以远程调用的过程。每个过程都有一个过程号。

程序和过程号列出了值的范围及其含义,并告诉您如何为您的RPC程序分配一个程序号。RPC网络数据库/ etc / rpc中提供了RPC服务名到程序号的映射列表。

 

———————————-

接口例程概述

RPC具有多个服务级别的应用程序接口。这些级别提供不同程度的控制,并以不同数量的接口代码来实现,以增加控制和复杂性的顺序。本节总结了每个级别上可用的例程。

简化的接口程序

简化的接口用于对其他计算机上的例程进行远程过程调用,并仅指定要使用的传输类型。此级别的例程用于大多数应用程序。描述和代码示例在简化接口一节中。

表2-1 RPC例程-简化级别

常规
功能
rpc_reg
在指定类型的所有传输上将过程注册为RPC程序
rpc_call
在指定的远程主机上远程调用指定的过程
rpc_broadcast
在指定类型的所有传输中广播呼叫消息

标准接口例程

标准接口分为顶层中间层专家层底层。这些接口使程序员可以更好地控制通信参数,例如正在使用的传输,对错误做出响应并重新发送请求之前要等待多长时间等。

顶级例程

在顶层,接口仍然很简单,但是程序必须在拨打电话之前创建客户端句柄,或者在接收呼叫之前创建服务器句柄。如果希望应用程序在所有传输上运行,请使用此接口。您可以在“顶层接口”中找到这些例程和代码示例的用法。

表2-2 RPC例程-顶层

常规
描述
clnt_create
通用客户端创建。该程序告诉clnt_create服务器位于何处以及要使用的传输类型。
clnt_create_timed
clnt_create相似,但使程序员能够指定在创建尝试期间尝试的每种传输类型所允许的最长时间。
svc_create
为指定类型的所有传输创建服务器句柄。该程序告诉svc_create使用哪个调度功能。
clnt_call
客户端调用一个过程以将请求发送到服务器。

中级例程

RPC的中间级别接口使您可以控制详细信息。在这些较低级别编写的程序更加复杂,但运行效率更高。中间级别使您可以指定要使用的传输方式。中级接口描述了这些例程和代码示例的用法。

表2-3 RPC例程-中级

常规
描述
clnt_tp_create
为指定的传输创建客户端句柄
clnt_tp_create_timed
类似于clnt_tp_create,但使程序员能够指定允许的最大时间
svc_tp_create
为指定的传输创建服务器句柄
clnt_call
客户端调用一个过程以将请求发送到服务器

专家级例程

专家级别包含一组较大的例程,可用于指定与运输相关的参数。专家级接口描述了这些例程和代码示例的用法。

表2-4 RPC例程-专家级别

常规
描述
clnt_tli_create
为指定的传输创建客户端句柄
svc_tli_create
为指定的传输创建服务器句柄
rpcb_set
调用rpcbind设置RPC服务和网络地址之间的映射
rpcb_unset
删除rpcb_set设置的映射
rpcb_getaddr
调用rpcbind获取指定的RPC服务的传输地址
svc_reg
将指定的程序和版本号对与指定的调度例程相关联
svc_unreg
删除svc_reg设置的关联
clnt_call
客户端调用一个过程以将请求发送到服务器

底层例程

底层包含用于完全控制运输选项的例程。底层接口 描述了这些例程。

表2-5 RPC例程-底层

常规
描述
clnt_dg_create
使用无连接传输为指定的远程程序创建RPC客户端句柄
svc_dg_create
使用无连接传输创建RPC服务器句柄
clnt_vc_create
使用面向连接的传输为指定的远程程序创建RPC客户端句柄
svc_vc_create
使用面向连接的传输创建RPC服务器句柄
clnt_call
客户端调用一个过程以将请求发送到服务器

———————————

标准接口

与RPC软件包的标准级别的接口可增强对RPC通信的控制。使用此控件的程序更加复杂。在这些较低级别上进行有效的编程需要对计算机网络基础知识有更多的了解。顶层,中间层,专家层和底层层是标准界面的一部分。

本节介绍如何通过使用较低级别的RPC库来控制RPC详细信息。例如,您可以选择传输协议,该协议只能通过NETPATH变量在简化的接口级别上完成 。为了使用这些例程,您应该熟悉顶层接口(TLI)。

下面显示的例程无法通过简化接口使用,因为它们需要传输句柄。例如,在简化接口上使用XDR例程进行序列化或反序列化时,无法分配和释放内存。

clnt_call()
clnt_destroy()
clnt_control()
clnt_perrno()
clnt_pcreateerror()
clnt_perror()
svc_destroy()

顶层介面

在顶层,应用程序可以指定要使用的传输类型,但不能指定特定的传输。此级别与简化接口的不同之处在于,应用程序在客户端和服务器中都创建了自己的传输句柄。

顶层界面的客户端

在下面的代码示例中假定头文件。

示例4-7 time_prot.h头文件

以下示例显示了使用顶级服务例程的简单日期服务的客户端。传输类型被指定为程序的调用参数。

示例4-8普通日期服务的客户端

如果NETTYPE在程序的调用未指定,则该字符串NETPATH被取代。当RPC库例程遇到此字符串时,NETPATH环境变量的值将控制传输选择。

如果无法创建客户端句柄,请使用clnt_pcreateerror()显示失败的原因。您还可以通过读取全局变量rpc_createerr的内容来获取错误状态。

创建客户端句柄后,clnt_call()用于进行远程调用。它的参数是远程过程号,用于输入参数的XDR过滤器,参数指针,用于结果的XDR过滤器,结果指针以及调用的超时时间。该程序没有参数,因此指定了xdr_void()。通过调用clnt_destroy()进行清理 。

到结合在前面的例子中允许客户创建句柄到30秒的时间,更换调用clnt_create()与对呼叫clnt_create_timed()作为显示在下面的代码段:

下面的示例显示了用于普通日期服务的服务器的顶级实现。

示例4-9用于简单日期服务的服务器

svc_create()返回其创建服务器处理的传输数。 time_prog()是由被称为服务功能()svc_run当一个请求指定其程序和版本号。服务器通过svc_sendreply()将结果返回给客户端。

当您使用rpcgen生成分派函数时,该过程返回后将调用svc_sendreply()。因此,在本示例中,必须在实际过程中将rslt声明为 静态svc_sendreply()是从调度函数内部调用的,因此rslt不声明为static

在此示例中,远程过程不接受任何参数。当必须传递参数时,下面列出的调用将获取,反序列化(XDR解码)并释放参数。

中级界面

在中间级别,应用程序直接选择要使用的传输方式。

中间层接口的客户端

以下示例显示了顶层接口中的时间服务的客户端 ,它是在RPC的中间层编写的。在此示例中,用户必须在命令行上命名进行呼叫的传输方式。

示例4-10中级时间服务客户端

在此示例中,netconfig结构是通过调用 getnetconfigent(netid)获得的。有关更多详细信息,请参见getnetconfig(3NSL)手册页和《编程接口指南》。在此级别上,程序将明确选择网络。

到结合在前面的例子中允许客户创建句柄到30秒的时间,更换调用clnt_tp_create()与对呼叫clnt_tp_create_timed()作为显示在下面的代码段:

中级接口的服务器端

以下示例显示了相应的服务器。启动服务的命令行必须指定通过其提供服务的传输方式。

示例4-11中级时间服务服务器

专家级界面

在专家级别,网络选择与在中间级别相同。唯一的区别是应用程序对CLIENTSVCXPRT句柄的详细信息的控制级别有所提高。这些示例说明了使用clnt_tli_create()svc_tli_create()例程执行的此控件 。有关TLI的更多信息,请参见《编程接口指南》

专家级界面的客户端

示例4-12显示了clntudp_create()的版本,该版本是使用clnt_tli_create()进行UDP传输的客户端创建例程。该示例显示了如何根据所选传输类型来选择网络。clnt_tli_create()用于创建客户端句柄并执行以下操作:

  • 传递一个打开的TLI文件描述符,该文件可能会绑定也可能不会绑定
  • 将服务器的地址传递给客户端
  • 指定发送和接收缓冲区的大小

示例4-12 RPC较低级别的客户端

使用setnetconfig()getnetconfig()endnetconfig()选择网络endnetconfig()不被调用,直到调用后clnt_tli_create(),附近的例子的端部。

可以将clntudp_create()传递给打开的TLI fd。如果未传递任何内容(fd == RPC_ANYFD), clntudp_create()将使用UDP的netconfig结构打开自己的名称,以查找要传递给t_open()的设备的名称。

如果远程地址未知(raddr-> sin_port == 0),则从远程rpcbind获取

创建客户端句柄后,可以使用对clnt_control()的调用对其进行修改。RPC库在销毁句柄时会关闭文件描述符,就像打开fd本身时调用clnt_destroy()一样。然后,RPC库设置重试超时期限。

专家级界面的服务器端

例4-13显示了例4-12的服务器端。它称为svcudp_create()。服务器端使用svc_tli_create()

svc_tli_create()在应用程序需要精细控制时使用,尤其是在:

  • 将打开的文件描述符传递给应用程序。
  • 传递用户的绑定地址。
  • 设置发送和接收缓冲区的大小。在FD传入时参数可以是自由的。然后将其绑定到一个给定的地址,地址存储在一个手柄。如果绑定地址设置为NULL,并且fd最初未绑定,则它将绑定到任何合适的地址。

使用rpcb_set()rpcbind注册服务。

示例4-13 RPC较低级别的服务器

此处的网络选择类似于clntudp_create()来完成。文件描述符未显式绑定到传输地址,因为svc_tli_create()会这样做

svcudp_create()可以使用打开的fd。如果没有提供,它将使用选定的netconfig结构打开一个自身。

底层界面

RPC的底层接口使应用程序可以控制所有选项。 clnt_tli_create()和其他专家级RPC接口例程均基于这些例程。您很少使用这些低级例程。

底层例程创建内部数据结构,缓冲区管理,RPC头等。这些例程的调用者(例如专家级例程clnt_tli_create())必须在客户端句柄中初始化cl_netidcl_tp字段。对于创建的句柄,cl_netid是传输的网络标识符(例如udp),而cl_tp是该传输的设备名称(例如/ dev / udp)。例程clnt_dg_create()clnt_vc_create()设置clnt_opscl_private字段。

底层接口的客户端

以下代码示例显示对clnt_vc_create()clnt_dg_create()的调用。

示例4-14底层客户

这些例程要求打开并绑定文件描述符。svcaddr 是服务器的地址。

底层接口的服务器端

以下代码示例是创建底层服务器的示例。

示例4-15底层服务器

服务器缓存

svc_dg_enablecache()启动数据报传输的服务缓存。仅在服务器过程是“仅一次”操作类型的情况下才应使用缓存。多次执行缓存的服务器过程会产生不同的结果。

此函数为服务端点xprt分配一个重复的请求缓存,该缓存足够大以容纳cache_size条目。如果服务包含结果不同的过程,则需要重复的请求缓存。启用缓存后,将无法禁用它。

低层数据结构

以下数据结构信息仅供参考。实现可能会改变。

第一个结构是在<rpc / clnt.h>中定义的客户端RPC句柄。低级实现必须为每个连接提供并初始化一个句柄,如以下代码示例所示。

示例4-16 RPC客户端句柄结构

客户端句柄的第一个字段是在<rpc / auth.h>中定义的身份验证结构。默认情况下,此字段设置为AUTH_NONE。客户端程序必须适当地初始化cl_auth,如以下代码示例所示。

示例4-17客户端身份验证句柄

AUTH结构中,ah_cred包含调用方的凭据,而ah_verf包含用于验证凭据的数据。有关详细信息,请参见身份验证

以下代码示例显示了服务器传输句柄。

示例4-18服务器传输句柄

下表显示了服务器传输句柄的字段。

xp_fd
与句柄关联的文件描述符。两个或多个服务器句柄可以共享同一文件描述符。
xp_netid
在其上创建句柄的传输的网络标识符(例如udp),而xp_tp是与该传输关联的设备名称。
xp_ltaddr
服务器自己的绑定地址。
xp_rtaddr
远程呼叫者的地址(因此可以随呼叫而变化)。
xp_netid xp_tp xp_ltaddr
svc_tli_create()和其他专家级例程初始化 。

其余字段由底层服务器例程svc_dg_create()svc_vc_create()初始化 。

对于面向连接的端点,在请求并接受服务器连接之前,以下字段无效:

xp_fd
xp_ops()
xp_p1()
xp_p2
xp_verf()
xp_tp()
xp_ltaddr
xp_rtaddr()
xp_netid()

承接各种网站开发与修改、爬虫、数据采集分析、小程序等任务

Html+Css+JS+PHP+Nodejs+Python

专治网站各种不服

一起探讨,互相学习,共同进步!有事儿您说话。

This entry was posted in C/C++ and tagged , , , , by 织梦先生. Bookmark the permalink.