级别: 初级 郭 路 (gl2_public@sina.com), Technical Manager
2001 年 6 月 01 日 传递XML信息流的通信协议基本可分为两类:与XML无关及与XML有关的。当协议与XML无关时XML文档被视为一般的文本数据,因此可以与各种通用的网络通信方式结合。当协议与XML有关时,即传递数据的载体必须为XML格式,目前这样的协议有XML-RPC、SOAP、WDDX等,它们都属于应用层协议。由于第一类方法中,XML信息的处理与一般信息无二,即使用传统的网络通信方法即可,因此本文仅作简要介绍;而对第二类方法,本文将会逐一做较为详细的说明,并试图分析XML-RPC、SOAP、WDDX等协议之间的异同。
与XML无关的传输模式
通常在分布式的企业内部管理系统中,用于传递数据的常见方法有:
- 使用传统通信协议:如TCP/IP、SOCKET、IPX/SPX等;
- 使用消息队列传递:如MessageQ、MSMQ、MQSeries等;
- 使用邮件服务系统:如Exchange Server、Lotus等;
- 使用分布式应用组件模型:如CORBA、DCOM、RMI等;
- 使用数据库服务器:如ODBC、ADO、OLE DB数据源等;
对于如TCP、IP、SOCKET、IPX等处于传输层或传输层以下的协议,信息一般以纯数据流形式传递。或者将数据拆分打包(如TCP、UDP、IPX、SPX等),或者指定存有传递数据的发送缓冲区(如SOCKET),通信协议并不了解所传递的内容,此时的XML信息被整个视为一个字符整串传递。
消息队列传递通常是针对某种MQ应用软件而言的(本文中对消息的定义仅在应用层,是一种高级的通讯模式,与Windows编程模型中的事件消息定义不同),对于这类软件,消息是网络数据传递的基本方式,一般用一个消息队列服务器来统一管理消息,消息大致可分为数据报、请求、应答、报告等基本类型,不管何种类型,消息都由消息描述符与实际数据组成。通常消息服务器不需了解消息的内容,不过由于消息客户端一般总是需要定制的,我们可以使用DTD与DOM对消息进行约束,通过对MQ
Client的二次开发(发送端与接收端都需要),使消息面向XML。目前已有包括微软在内的一些MQ软件提供商表示将在其下一代消息软件中支持XML,由于消息采用XML规范,因此可以轻易地实现异构网络的通信,比如说,可以开发UNIX版的MSMQ客户端,而原来MSMQ必须基于Windows平台。
与消息队列传递相似的是邮件服务系统,其基本原理是在网络中建立一台邮件服务器,即邮局,每一个客户可以在邮局中建立自己的邮箱并设置收信密码,并将自己的邮箱地址发布到通讯簿,其它客户可以将电子邮件发到其邮箱中,而收件人通过密码打开邮箱取信。通常我们使用SMTP协议发信,POP3协议收信,二者都是应用层协议。电子邮件是一种非常成熟的数据交互模式,在此基础上建立起的一系列规范已成为工业标准,如邮件的加密、数字签名、多媒体传输(MIME)等。通常采用邮件发送XML数据有两种形式,作为电子邮件原文或附件,在应用上二者没有大的区别。目前各邮件服务系统的邮件管理都是通过后台的数据库管理实现的,除了使用指定的客户端收发邮件外,通常也都提供了直接访问邮局的编程接口(如可以通过ADO接口访问Exchange
Server),开发人员可以由此定制自己的邮件客户端。
与前三类交互方式不同,由于分布式组件模型支持常见的数据类型(与Schema和DTD兼容),因此我们针对不同类型的XML文档--以数据为中心的(Data-Centric)或以文档为中心的(Document-Centric),可以采取不同的传输策略,对于以文档为中心的XML信息(如标书,通知,信函等),通常还是将整个文档打包处理,对于以数据为中心的XML信息(如采购订单、生产计划等),由于可以非常方便地用结构数据类型表示,因此我们可以对其进行如下处理:
此时网络通信的输入输出源均为XML格式,而实际数据的传输则使用与编程模型相对应的格式。这种方法与WDDX非常相似,事实上它与WDDX的主要区别就在于二者数据结构的映射顺序正好相反(关于WDDX将在下一节介绍)。这样做的好处在于:
- 少数据冗余(XML由于包含大量标记,因此会造成一定数据冗余,同时通过映射,可以过滤掉不需要传递的子元素和属性);
-
强数据约束(XML元素中数据通常被统一视为字符串类型,因此很难判断基本数据类型的错误,通过结构类型的映射可以对每个叶子结点作显式的类型声明);
-
易实现数据的安全传输(XML本身不包含数据的安全加密,而诸如DCOM、CORBA这样的分布式组件模型中都已内含完整的数据安全策略,使用组件模型开发人员可以透明的实现数据的安全传递);
-
提高数据传递的灵活性(除了前面提到可以过滤不需要的子元素和属性外,通过映射与反映射,可以不使用XSLT就实现XML到XML的转换)。
目前已有一些CORBA软件商声称将在其产品中支持SOAP协议,这样今后我们在开发时也许就可以无需映射直接传递XML数据了。
数据库服务器同样支持常见的基本数据类型,这种数据交互模式一般用于应用层与数据层之间的数据交换,最为典型的例子就是将应用服务器输出的XML数据流保存到数据库中。由于数据库高度结构化的特性,我们很少用它来传输以文档为中心的XML信息(除非将一个XML文档保存到单个字段中),通常情况下,我们可以使用一个XML-数据库中间件(如ORACLE的XML
SQL Utility for Java and XSQL
Servlet,InfoShark的XMLShark等)来封装XML数据<->数据库记录集的映射以及网络间的数据传输。当然,也可以使用DOM或SAX解析出XML文档子元素,然后通过ODBC等数据库接口传输到远端的数据库中,对于像ADO这样本身就已支持XML的数据库编程接口(可以将一个XML文档直接当作记录集使用,或将记录集直接输出为XML格式),只要将XML信息的表示稍加约束,添加一些附加的映射信息,无需DOM解析便可直接传递。
基于XML的数据传输模式
XML-RPC协议
如果有一种数据传输协议,无需映射、打包,只需附加少许对XML文档格式的约束,便可以直接传输XML文档,显然,这将大大简化我们数据传输的流程。XML-RPC正是这样的一种应用层传输协议。
首先我们将XML数据视作简单的文本,此时可以选择HTTP为数据传输协议,HTTP不仅是最简单最通用的原文传输协议,其优点还在于几乎所有的防火墙都允许HTTP(缺省80端口)通过,换言之,几乎所有的计算机其HTTP
80端口都是开放的。这种特点在企业局域网中也许并不明显,因为我们知道需要交互信息的是哪两台计算机,并可以要求系统管理员开放出固定的通信端口。然而在一个互联网电子商务的环境中,设想一下,假设某个供应商访问了我的网站,并申请成为我们的会员,当他按了WEB页面上"确定申请"的按钮后,我希望可以POST一份会员手册给他,我不知道该供应商的计算机上是否装有防火墙,我唯一可以确定的,就是其HTTP端口是开放的,为了保证我POST会员手册的动作不会失败,显然我应该选择通过HTTP端口进行手册的传输。
XML-RPC的实现是基于HTTP
POST方法的,也就是说XML-RPC的传输数据流遵循HTTP格式,它可以是手工建立的,也可以是通过XML-RPC接口自动生成的。事实上,与其说XML-RPC是一种传输协议,倒不如说其是一种网络编程接口定义规范更准确些,因为它封装了HTTP(有点像是一个SHELL),实际的数据传输全部由HTTP完成,通过这种接口规范,客户端可以指定目标计算机,并将XML数据(包括目标方法和参数)传递给它,目标计算机通过XML-RPC接口得到XML数据,处理后将结果值以同样的方式(XML报文格式)返回给客户端。由于XML-RPC实际使用的是HTTP协议,因此在传输过程中,它会沿袭HTTP协议本身的各项属性,比如说,除了前面所说的绕过防火墙外,还可以对XML-RPC使用SSL、S-HTTP等安全协议。
首先来看如下的一段XML-RPC请求:
POST /RPC2 HTTP/1.0
//请求报头
User-Agent: Frontier/5.1.2 (WinNT)
Host: 202.96.96.68
Content-Type: text/xml
Content-length: 280
<?xml version="1.0"?>
//请求报文
<methodCall>
<methodName>CreateOrderForm</methodName>
//调用方法名:新建采购订单
<params>
//参数组
<param><value><string>鸿雁电器</string></value></param>
//指定采购供应商
<param><value><string>三向插头</string></value></param>
//指定采购物品
<param> <value><i4>2000</i4></value> </param>
//指定采购数量
<param><value><dateTime.iso8601>
20010321T12:00:00
//指定交货时间
</dateTime.iso8601></value></param>
</params>
</methodCall>
|
上述请求的XML-RPC响应如下:
HTTP/1.0 200 OK
//响应报头
Connection: close
Content-length:
Content-Type: text/xml
Date: Fri, 16 Mar 2001 14:30:01 GMT
Server: Win Server
<?xml version="1.0"?>
//响应报文
<methodResponse>
<params>
<param>
<value><string>SX0002001</string></value>
//订单新建成功,返回订单号
</param>
</params>
</methodResponse>
|
顾名思义,XML-RPC是一种通过XML实现远程方法调用(Remote Procedure Calls)的手段,它能够完成与CORBA、DCE RPC、SUN
RPC相类似的功能,即调用远端计算机上的方法(程序),并将结果集返回。然而由于使用了XML,使其在应用中具有了无与伦比的灵活性,XML-RPC是一个纯粹的有线协议,其规范是完全开放的,不要求使用任何第三方的ORB技术(微软或其它厂商),事实上,由于XML-RPC是如此简单,我们完全可以自己编写一个API来实现其调用。正如上面的范例所示,XML-RPC报头遵循HTTP规范,消息体使用规范的XML格式,其包含着在远程服务器上执行的方法以及这些方法所使用的全部参数。返回的响应也是基于XML的。有关XML-RPC规范的简要说明如下:
- 请求报头格式要求:
- 报头遵循HTTP规范;
- 首行中HTTP动作必须为POST;
-
如果服务器仅处理XML-RPC调用,首行中URI可以不指定(为空或一个单斜线);但如果服务器处理的是混合的HTTP请求,则应使用URI指定调用目标路径,本例中URI为"RPC2";
- 用户代理(User-Agent)与主机(Host)必须指定;
- 消息体格式必须指定为text/xml;
- 报头末行必须给出正确的消息体长度(Content-length);
- 请求报文格式要求:
- 报文遵循XML规范;
- 全部请求应包含在一个<methodCall>元素中;
-
<methodCall>元素中必须包含一个子元素<methodName>,该子元素包含一个字符串,用于描述一个将要调用的远程方法名;
- 如果该远程方法需要指定参数,则在<methodCall>元素中必须包含一个<params>子元素;
- <params>元素中可包含0到多个<param>子元素,每个<param>子元素对应一个输入参数项;
-
<param>元素的基本格式为:<param><value><数据类型>输入参数值</数据类型></value></param>;
-
<param>元素的数据类型可以是简单数据类型,如逻辑型(boolean)、整型(int或i4)、字符串型(string)、双精度型(double)、日期/时间型(dateTime.iso8601)、二进制编码(base64),也可以是数组(array)和结构(struct);
- 逻辑型参数值可以为"0"(表示错误)和"1"(表示正确);
- 整型参数值是一个4字节的有符号整数,0只有一位,不允许有空格;
- 字符型参数值必须由合法的ASCⅡ文本组成,特殊字符必须用组合编码表示,如用"&
lt"表示"<",用"&"表示"&";
- 双精度型参数值定义为双精度带符号浮点数,包含一个正号或负号,不能包含空格;
- 日期/时间型参数值的格式为"YYYYMMDDTHH24:MM:SS",即"年月日T小时(24小时制):分钟:秒";
- 二进制编码信息采用Base 64标准传输;
-
数组元素的基本格式为:<array><data>A1A2…An</data></array>,其中n为大于等于1的整数,A的基本格式为:<value><数据类型>输入参数值</数据类型></value>,数组中允许嵌套;
-
结构元素的基本格式为:<struct>子成员1子成员2…子成员n</struct>,其中n为大于等于1的整数,子成员的基本格式为:<member><name>子成员名</name><value><数据类型>输入参数值</数据类型></value></member>,同一结构中不同子成员(同一级)的成员名不可相同,结构中同样允许嵌套,由于子成员采用成员名作为唯一标志,因此在结构中各子成员的顺序是允许改变的。
- 响应报头格式要求:
- 报头遵循HTTP规范;
- 首行中HTTP响应信息必须为200 OK;
- 消息体格式必须指定为text/xml;
- 报头末行必须给出正确的消息体长度(Content-length);
- 响应报文格式要求:
- 报文遵循XML规范;
- 全部请求应包含在一个<methodResponse>元素中;
-
当XML-RPC请求处理成功时,返回的<methodResponse>元素中必须包含一个唯一的<params>子元素,<params>子元素中又包含一个唯一的<param>子元素,该子元素的格式为:<param><value><数据类型>返回结果值</数据类型></value></param>,其中数据类型可以嵌套;
-
当XML-RPC请求处理失败时,返回的<methodResponse>元素中必须包含一个<fault>子元素,该子元素中包含一个唯一的<value>子元素,<value>元素中又包含一个唯一的<struct>结构类型子元素,在<struct>结构中包含两个数据元素项,其中一个数据元素名为"faultCode",其值为<int>格式,指出请求处理失败的错误代码;而另一个数据元素名为"faultString",其值为<string>格式,指出请求处理失败的错误原因。<fault>元素的具体格式如下所示:
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>错误代码</int></value>
</member>
<member>
<name>faultString</name>
<value><string>错误原因描述</string></value>
</member>
</struct>
</value>
</fault>
|
通过以上对XML-RPC规范的描述可以发现,在基于XML-RPC的方法调用和数据传递中,客户端与服务器端是完全独立的,XML-RPC报文是建立二者相互联系的唯一途径,XML-RPC对于计算机平台几乎没有限制(包括操作系统与编程语言)。事实上,任何一种支持HTTP协议的编程语言都可以支持XML-RPC编程,我们可以想象一个运行在Windows2000上的DCOM用户现在可以调用在UNIX
APACHE服务器上的Perl程序(基于DCOM与Perl的XML-RPC开发包均已实现)。这种松散连接的特性原本出现在单纯的网络通信,XML-RPC将其扩展到分布式组件应用的范畴,而类似于DCOM、CORBA、RMI等基于紧密集成系统的传统分布式组件技术对于环境的需求则是非常严格的。
XML-RPC规范的内容非常简单(有兴趣的人可以进入
http://www.xmlrpc.com/spec
参看由UserLand Software,Inc.发布的"XML-RPC
Specification"),然而令人惊奇的是,对于大多数分布式应用(尤其是基于互联网的B2B应用)而言,这种规范居然就已足够了,尽管XML-RPC的执行速度会较纯粹的DCOM、CORBA低,不过对于一个开放的互联网环境,由于网络带宽引起的延时才是主要的,因此我们通常不会察觉到由XML-RPC引起的延时。
使用XML-RPC传递XML数据是非常方便的,正如我们前面所看到的,在请求报文中我们还可以给出处理的方法名(对于纯数据传输的情况,可以在服务器端定义一个"Send"功能),如果已生成物理的XML文档,只要定义一个HTTP报头就可以了。然而对于项目开发而言,XML-RPC所给定的XML报文格式并不具备广泛性,通常请求报文的参数部分会是我们所要传输的主要内容,然而在XML-RPC中其格式却显得过于冗长并缺少灵活性,像这样的XML数据除了用于XML-RPC传输外,并不适合一般的XML处理。关于这点,正是下一节"SOAP协议"所要解决的。
以下是XML-RPC的开发工具包链接清单:
关于作者  | 
|  | 郭路,杭州大学计算机系92届本科应用专业,曾先后就职于浙江省纺织经贸总公司计算机中心、思能软件、华企、飞时达等软件公司,担任技术主管,主要从事于企业
MIS、GIS、ERP 及电子商务项目的开发管理和系统分析,对 IBM、微软、SUN、Autodesk 等公司的企业级产品有较深的研究及理解。 |
对本文的评价
|