### 在 PHP 中利用 XML 技术构造远程服务(1)

未来的Web将是以服务为中心的Web，XML_RPC标准使得编写和应用服务变得非常简单。本文介绍XML_RPC标准及其PHP实现，并通过实例示范了如何在PHP中开发XML_RPC服务和客户程序。
一、服务式Web
从内容提供商所采用的简单方法到UDDI（Universal Description，Discovery and Integration）的未来构想，业界已经有大量关于“服务式Web”的说明和评论。就Web的初创阶段来说，它只是一个文档的集散地，提供的只是一些可浏览的信息。随着Web的发展，在Web上运行服务越来越具有吸引力。未来，Web将成为企业为客户和其他企业提供便捷服务的载体。B2B和B2C模式间的协同就可以看成是一种服务式Web。
一个很重要的问题是，Web上究竟可以提供哪些服务？Web能够提供的服务非常多，其中有些服务现在已经在使用，有些服务在不久的将来就会出现。为了说明问题，下面列出了一小部分可以通过Web提供的服务：

面向主题的垂直搜索引擎。
供用户查找信息的知识库。
用户可以请教问题的专家系统。
银行服务。
新闻和信息出版服务。
数字化支付相关的服务。
图形处理服务。
卫生和健康服务。

那么，企业和组织通过Web提供服务的正确途径是什么呢？这是一个很重要的问题。今天，有些服务提供HTML界面，它们通过文档的形式提供服务，但在服务界面的背后隐藏着什么？在占领Web的竞赛中，Web浏览器并不孤单，移动电话、手持设备以及微波炉之类的设备都想要访问Web、查询数据库、转换数据、提取信息，等等。要实现真正的服务式Web，在表现层（HTML）之下应该还有另外一层。
二、XML_RPC标准
XML或许是近10年来最为重要的标准，XML词汇表（Vocabulary）为企业构造服务环境提供了基石。要构建服务式Web就有必要学习XML_RPC标准，这不仅是因为XML_RPC对于把服务放到Web上很有用，而且因为XML_RPC是一种已经成形的、很容易采用的标准。对于B2B服务来说，提供服务的标准是极其重要的，共同遵循标准的公司可以利用其它公司提供的服务获得快速的增长。无法想象在各种私有的服务标准之上可以建立起真正的服务式Web，服务必须有一种可以遵循的标准。
XML_RPC是一种面向Internet分布式处理的标准。RPC即为Remote Procedure Call（远程过程调用）的缩写，它是一种远程调用机制，用于调用可能驻留在其他机器之上以及可能用其他语言编写的过程。远程过程调用是分布式计算的重要支柱。例如，在一个分布式计算环境中，我们可以寻找和利用在其他机器上运行的执行加法和减法操作的过程，执行加法操作的过程可能用APL编写、在RS6000机器上运行，执行减法操作的过程可能用C编写、在Unix上运行。其他要使用这种分布式计算器的开发者同样可以利用它们，或者他也可以选用另外更好的计算器。
在RPC中，过程（Procedure）是最主要的构件，服务器提供的就是供客户端调用的过程。过程可以接收参数并返回结果。XML_RPC以HTTP作为协议载体，通过发送和接收数据的XML词汇表实现RPC机制。XML_RPC服务器接收XML_RPC请求并返回XML_RPC应答，XML_RPC客户程序发送XML_RPC请求并接收XML_RPC应答。服务器和客户必须按照XML_RPC标准的要求处理应答和请求。
三、XML_RPC协议
完整的XML_RPC规范可以在http://www.xmlrpc.com/spec找到。下面是其要点说明。

3.1 XML_RPC请求

XML_RPC请求应该是HTTP POST请求，它的正文是XML格式。请求的XML部分格式如下：

＜?xml version="1.0" ?＞ ＜methodCall＞ ＜methodName＞examples.getStateName＜/methodName＞ ＜params＞ ＜param＞
＜value＞＜i4＞41＜/i4＞＜/value＞
＜/param＞
＜/params＞
＜/methodCall＞

指定数据发送到哪里的URL并未在这里指定。如果服务器专门用来进行RPC处理，它可能是“/”。上述XML文档中的有效载荷是一个“methodCall”结构。methodCall必须包含一个“methodName”子元素，“methodName”子元素包含一个描述待调用方法的字符串。如何解释“methodName”的内容完全由服务器决定，例如它可以是一个执行文件的名字，可以是数据库中记录的名字，或者任何其他东西。如果过程接收参数，“methodCall”可以包含一个“params”元素以及若干个“param”子元素。每一个“param”元素包含一个带有类型描述符的值，类型描述符如下表所示：

标记 | 说明
＜i4＞或＜int＞ | 四字节的带符号整数，如12
＜boolean＞ | 0（false），或1（true）
＜string＞ | 字符串，如“Hello World”
＜double＞ | 双精度带符号浮点数，如-12.214
＜dateTime.iso8601＞ | 日期/时间，如19980717T14:08:55
＜base64＞ | base64编码的二进制数据，如eW91IGbid0IHJlQgdGhpcyE

3.1.1 结构
值可以是一个结构，结构用<struct>元素描述。每个<struct>包含多个<member>，每个<member>包含一个<name>和一个<value>。下面是一个由两个元素构成的结构：

＜struct＞ ＜member＞ ＜name＞name＜/name＞ ＜value＞＜string＞member1＜/string＞＜/value＞ ＜/member＞
＜member＞
＜name＞member2＜/name＞
＜value＞＜i4＞19＜/i4＞＜/value＞
＜/member＞
＜/struct＞

<struct>可以嵌套，任意<value>可以包含<struct>或者任意其它类型，包括<array>。
3.1.2 数组
值可以是数组类型，数组用<array>元素描述。每个<array>元素包含一个<data>元素，<data>元素里面可以包含任意多个<value>元素。下面是数组元素的一个例子：

＜array＞ ＜data＞ ＜value＞＜boolean＞0＜/boolean＞＜/value＞ ＜value＞＜i4＞9＜/i4＞＜/value＞ ＜value＞＜string＞Hello＜/string＞＜/value＞
＜/data＞
＜/array＞

<array>元素没有名字。如前例所示，<array>元素的值可以是各种类型。<array>元素可以嵌套，任何<value>都可以包含<array>或者其他类型，如上面介绍的<struct>。

3.2 XML_RPC应答

XML_RPC应答是一个HTTP应答，内容类型是text/xml。应答正文的格式如下：

＜?xml version="1.0"?＞ ＜methodResponse＞ ＜params＞ ＜param＞ ＜value＞＜string＞ABCDEFG＜/string＞＜/value＞
＜/param＞
＜/params＞
＜/methodResponse＞

<methodResponse>可能包含一个<params>结构，或者可能包含一个<fault>结构，具体由过程调用是否成功决定。<params>结构与XML请求中的一样，<fault>元素的语法如下：

＜fault＞ ＜value＞ ＜struct＞ ＜member＞ ＜name＞faultCode＜/name＞
＜value＞＜int＞4＜/int＞＜/value＞
＜/member＞
＜member＞
＜name＞faultString＜/name＞
＜value＞＜string＞Error!＜/string＞＜/value＞
＜/member＞
＜/struct＞
＜/value＞
＜/fault＞