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


Posted in PHP onOctober 09, 2006

四、基于XML_RPC的Web服务
利用XML_RPC构造和使用服务是很方便的。企业为自己提供的各种服务部署XML_RPC服务器,用户、客户软件和客户企业就可以使用这种服务构造出高端服务或者面向最终用户的应用。这种提供更有效、廉价和优质服务的竞争将极大地提高应用服务的质量。

但这里还存在一些问题有待解决,例如怎样编目、索引、搜索Web上的服务?UDDI试图解决这个问题,不过这个标准并不简单,而且业界对它的反应也尚未明了。然而,在企业内部应用XML_RPC不仅能够改善代码的可重用性,而且还会带来一种全新的分布式计算模式,在此后的数年中它必将成为一种重要的知识财富。XML_RPC的发展从解决分布式计算问题以及成为服务式Web的基本层面开始,从而获得了一个非常好的开端,其后必将紧随着人们对该标准的热衷。既然如此,现在就让我们来看看XML_RPC的实际应用吧!

4.1 在PHP中应用XML_RPC

对于提供Web服务来说,PHP是一种非常理想的语言。我们只需编写好PHP代码然而把它放到一个合适的位置,就立即有了一个可通过URL“调用”的服务。PHP中的XML_RPC实现可能复杂也可能简单,但我们拥有许多种选择。这里我们选用的是来自Useful Information Company的XML_RPC实现,它的代码和文档可以从http://xmlrpc.usefulinc.com/下载。

这个XML_RPC实现的基本类涉及两个文件:

xmlrpc.inc:包含XML_RPC的php客户端所需要的类

xmlrpcs.inc:包含XML_RPC的php服务器所需要的类

4.2 客户端

编写XML_RPC客户端意味着:

1.创建一个XML_RPC请求消息

2.设置XML_RPC参数

3.创建一个XML_RPC消息

4.发送消息

5.获得应答

6.解释应答

请看下面这个例子:

<?php
$f=new xmlrpcmsg('examples.getStateName',array(new xmlrpcval(14, "int")));
$c=new xmlrpc_client("/RPC2", "betty.userland.com", 80);
$r=$c->send($f);
$v=$r->value();
if (!$r->faultCode()) {
print "状态代码". $HTTP_POST_VARS["stateno"] . "是" .
$v->scalarval() . "<BR>";
print "<HR>这是服务器的应答<BR><PRE>" .
htmlentities($r->serialize()). "</PRE><HR>n";
} else {
print "错误: ";
print "代码: " . $r->faultCode() .
" 原因: '" .$r->faultString()."'<BR>";
}
?>

在这个例子中,我们先创建了一个调用“examples.getStateName”方法的XML_RPC消息,并传递了一个类型为“int”值为14的整数参数。然后,我们创建了一个描述待调用URL(路径、域和端口)的客户。接着,我们发送了消息,接收应答对象并检查错误。如果不存在错误,我们就显示结果。

编写RPC客户程序时要用到的主要函数如下:

创建客户用:

$client=new xmlrpc_client($server_path, $server_hostname, $server_port);

发送消息的方法是:

$response=$client->send($xmlrpc_message);

它返回的是xmlrpcresp的一个实例。我们所传递的消息是xmlrpcmsg的实例,它用如下方法创建:

$msg=new xmlrpcmsg($methodName, $parameterArray);

methodName是待调用的方法(过程)的名字,parameterArray是xmlrpcval对象的php数组。例如:

$msg=new xmlrpcmsg("examples.getStateName", array(new xmlrpcval(23, "int")));

xmlrpcval对象可以用如下形式创建:

<?php
$myVal=new xmlrpcval($stringVal);
$myVal=new xmlrpcval($scalarVal, "int" | "boolean" | "string" | "double" | "dateTime.iso8601" | "base64");
$myVal=new xmlrpcval($arrayVal, "array" | "struct");
?>

第一种形式创建的是xmlrpc字符串值。第二种形式创建的是描述值和类型的值。第三种形式通过在数组之类的结构中组合其他xmlrpc值创建复杂的对象,例如:

<?php
$myArray=new xmlrpcval(array(new xmlrpcval("Tom"), new xmlrpcval("Dick"),new xmlrpcval("Harry")), "array");
$myStruct=new xmlrpcval(array(
"name" => new xmlrpcval("Tom"),
"age" => new xmlrpcval(34, "int"),
"geek" => new xmlrpcval(1, "boolean")),"struct");
?>

应答对象是xmlrpcresp类型,通过调用客户对象的send方法获得。在服务器端,我们可以通过如下方式创建xmlrpcresp类型的对象:

$resp=new xmlrpcresp($xmlrpcval);

而在客户端,则使用如下方法从应答获取xmlrpcval:

$xmlrpcVal=$resp->value();

接下来我们就可以用下面这种方式获取描述应答结果的PHP变量:

$scalarVal=$val->scalarval();

对于复杂的数据类型,有两个函数非常有用,这两个函数都在xmlrpc.inc内:

$arr=xmlrpc_decode($xmlrpc_val);

该函数返回一个PHP数组,其中包含了xmlrpcval变量$xmlrpc_val之内的数据,这些数据已经被转换成PHP本身具有的变量类型。

$xmlrpc_val=xmlrpc_encode($phpval);

该函数返回一个xmlrpcval类型的值,其中包含了$phpval描述的PHP数据。对于数组和结构,此方法能够进行递归分析。注意,这里不存在对非基本数据类型(如base-64数据,或者日期-时间数据)的支持。

4.3 服务器端

利用xmlrpcs.inc提供的类编写服务非常简单。要创建一个服务,我们按照如下方式创建xmlrpc_server的实例:

<?php
$s=new xmlrpc_server( array("examples.myFunc" =>
array("function" => "foo")));
?>

传递给xmlrpc_server构造函数的是一个联合数组的联合数组。过程“examples.myFunc”调用“foo”函数,由于这个原因foo被称为方法句柄。

编写方法句柄很简单。下面是一个方法句柄的骨架:

<?php
function foo ($params) {
global $xmlrpcerruser; // 引入用户错误代码值
// $params是一个xmlrpcval对象的数组
if ($err) {
// 错误条件
return new xmlrpcresp(0, $xmlrpcerruser+1, // 用户错误1
"Error!");
} else {
// 成功
return new xmlrpcresp(new xmlrpcval("Fine!", "string"));
}
}
?>

可以看到,程序检查了错误,如存在错误则返回错误(从$xmlrpcerruser+1开始);否则如果一切正常,则返回描述操作成功信息的xmlrpcresp。

五、应用实例
在下面这个例子中我们将构造一个服务。对于给定的数值n,服务返回n*2。客户端利用该服务计算5*2的值。

服务器端的代码如下:

<?php
include("xmlrpc.inc");
include("xmlrpcs.inc");
function foo ($params)
{
global $xmlrpcerruser; // 引入用户错误代码值
// $params是xmlrpcval对象的一个数组
$vala=$params->params[0];
$sval=$vala->scalarval();
$ret=$sval*2;
return new xmlrpcresp(new xmlrpcval($ret, "int"));
}
$s=new xmlrpc_server( array("product" =>
array("function" => "foo")));
?>

客户端代码如下:

<?php
include("xmlrpc.inc");
if ($HTTP_POST_VARS["number"]!="") {
$f=new xmlrpcmsg('product',array(new xmlrpcval($HTTP_POST_VARS["number"], "int")));
$c=new xmlrpc_client("/xmlrpc/servfoo.php", "luigi.melpomenia.com.ar", 80);
$c->setDebug(0);
$r=$c->send($f);
$v=$r->value();
if (!$r->faultCode()) {
print "Number ". $HTTP_POST_VARS["number"] . " is " .
$v->scalarval() . "<BR>";
print "<HR>来自服务器的结果!<BR><PRE>" .
htmlentities($r->serialize()). "</PRE><HR>n";
} else {
print "操作失败: ";
print "代码: " . $r->faultCode() .
" 原因: '" .$r->faultString()."'<BR>";
}
}
print "<FORM METHOD="POST">
<INPUT NAME="number" VALUE="${number}">
<input type="submit" value="go" name="submit"></FORM><P>
输入一个数值";
?>

结束语:XML_RPC服务的运作还涉及其他许多基础设施和基础工作,如分布式过程的编目和索引机制,又如在编程语言中处理XML_RPC的更好接口等。有关XML_RPC和服务式Web的报道非常多,让我们密切关注它们的发展吧!

PHP 相关文章推荐
PHP 存取 MySQL 数据库的一个例子
Oct 09 PHP
php 购物车实例(申精)
May 11 PHP
PHP XML操作的各种方法解析(比较详细)
Jun 17 PHP
php类声明和php类使用方法示例分享
Mar 29 PHP
PHP使用Session遇到的一个Permission denied Notice解决办法
Jul 30 PHP
PHP保存带BOM文件的方法
Feb 12 PHP
PHP实现算式验证码和汉字验证码实例
Mar 09 PHP
PHP实现基于栈的后缀表达式求值功能
Nov 10 PHP
LaravelS通过Swoole加速Laravel/Lumen详解
Mar 02 PHP
php连接mysql数据库最简单的实现方法
Sep 24 PHP
PHP pthreads v3下的Volatile简介与使用方法示例
Feb 21 PHP
PHP实现长轮询消息实时推送功能代码实例讲解
Feb 26 PHP
把从SQL中取出的数据转化成XMl格式
Oct 09 #PHP
JAVA/JSP学习系列之四
Oct 09 #PHP
JAVA/JSP学习系列之二
Oct 09 #PHP
递归列出所有文件和目录
Oct 09 #PHP
不用iconv库的gb2312与utf-8的互换函数
Oct 09 #PHP
PHP的历史和优缺点
Oct 09 #PHP
新版PHP将向Java靠拢
Oct 09 #PHP
You might like
关于PHP中操作MySQL数据库的一些要注意的问题
2006/10/09 PHP
PHP语法自动检查的Vim插件
2014/08/11 PHP
ThinkPHP框架设计及扩展详解
2014/11/25 PHP
php中关于socket的系列函数总结
2015/05/18 PHP
php-redis中的sort排序函数总结
2015/07/08 PHP
php使用escapeshellarg时中文被过滤的解决方法
2016/07/10 PHP
THINKPHP在添加数据的时候获取主键id的值方法
2017/04/03 PHP
PHP面向对象五大原则之依赖倒置原则(DIP)详解
2018/04/08 PHP
鼠标图片振动代码
2006/07/06 Javascript
jQuery 使用手册(五)
2009/09/23 Javascript
不同的jQuery API来处理不同的浏览器事件
2012/12/09 Javascript
图标线性回归斜着移动到指定的位置
2013/08/16 Javascript
javascript获取和判断浏览器窗口、屏幕、网页的高度、宽度等
2014/05/08 Javascript
浅析jQuery Ajax请求参数和返回数据的处理
2016/02/24 Javascript
React Form组件的实现封装杂谈
2018/05/07 Javascript
vue.js 中使用(...)运算符报错的解决方法
2018/08/09 Javascript
微信小程序嵌入腾讯视频源过程详解
2019/08/08 Javascript
解决vue项目打包上服务器显示404错误,本地没出错的问题
2020/11/03 Javascript
Python实现矩阵转置的方法分析
2017/11/24 Python
详解python编译器和解释器的区别
2019/06/24 Python
Python分割训练集和测试集的方法示例
2019/09/19 Python
Python 定义只读属性的实现方式
2020/03/05 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
CSS 3.0 结合video视频实现的创意开幕效果
2020/06/01 HTML / CSS
香港优质食材和美酒专门店:FoodWise
2017/09/01 全球购物
Hush Puppies澳大利亚官网:舒适的男女休闲和正装鞋
2019/08/24 全球购物
德国的大型美妆个护电商:Flaconi
2020/06/26 全球购物
铭立家具面试题
2012/12/06 面试题
教育学习自我评价
2014/02/03 职场文书
分公司负责人任命书
2014/06/04 职场文书
奥运会口号
2014/06/13 职场文书
竞聘演讲稿开场白
2014/08/25 职场文书
2014院党委领导班子对照检查材料思想汇报
2014/09/24 职场文书
小学生光盘行动倡议书
2015/04/28 职场文书
2015年机关党建工作总结
2015/05/22 职场文书
idea下配置tomcat避坑详解
2022/04/12 Servers