在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 计算两个时间戳相隔的时间的函数(小时)
Dec 18 PHP
PHP 图片文件上传实现代码
Dec 29 PHP
有关于PHP中常见数据类型的汇总分享
Jan 06 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十五)
Jun 30 PHP
ThinkPHP文件上传实例教程
Aug 22 PHP
PHP实现股票趋势图和柱形图
Feb 07 PHP
PHP实现的简单缓存类
Jul 29 PHP
详解WordPress中简码格式标签编写的基本方法
Dec 22 PHP
phpinfo()中Loaded Configuration File(none)的解决方法
Jan 16 PHP
PHP反射原理与用法深入分析
Sep 28 PHP
Laravel 对某一列进行筛选然后求和sum()的例子
Oct 10 PHP
TP5框架使用QueryList采集框架爬小说操作示例
Mar 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的开合式多级菜单程序
2006/10/09 PHP
PHP 日期时间函数的高级应用技巧
2009/10/10 PHP
用php制作简单分页(从数据库读取记录)的方法详解
2013/05/04 PHP
Django中通过定时任务触发页面静态化的处理方式
2018/08/29 PHP
JS的反射问题
2010/04/07 Javascript
实现图片预加载的三大方法及优缺点分析
2014/11/19 Javascript
js中split和replace的用法实例
2015/02/28 Javascript
laypage分页控件使用实例详解
2016/05/19 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
Kotlin学习第一步 kotlin语法特性
2017/05/25 Javascript
详解JavaScript中的数组合并方法和对象合并方法
2018/05/11 Javascript
详解如何使用webpack打包JS
2018/06/21 Javascript
微信小程序开发之改变data中数组或对象的某一属性值
2018/07/05 Javascript
JS获取并处理php数组的方法实例分析
2018/09/04 Javascript
python人民币小写转大写辅助工具
2018/06/20 Python
Python 变量类型详解
2018/10/10 Python
Python 中 function(#) (X)格式 和 (#)在Python3.*中的注意事项
2018/11/30 Python
Python 中如何实现参数化测试的方法示例
2019/12/10 Python
matplotlib 多个图像共用一个colorbar的实现示例
2020/09/10 Python
python 基于selectors库实现文件上传与下载
2020/12/31 Python
css3背景_动力节点Java学院整理
2017/07/11 HTML / CSS
CSS3实现王者荣耀匹配人员加载页面的方法
2019/04/16 HTML / CSS
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
会计学个人自荐信模板
2013/12/13 职场文书
会计人员岗位职责
2014/03/19 职场文书
思想作风纪律整顿心得体会
2014/09/04 职场文书
初中生旷课检讨书范文
2014/10/06 职场文书
2015年社区精神文明工作总结
2015/05/26 职场文书
2020年基层司法所建设情况调研报告
2019/11/30 职场文书
php引用传递
2021/04/01 PHP
Javascript中的解构赋值语法详解
2021/04/02 Javascript
分析ZooKeeper分布式锁的实现
2021/06/30 Java/Android
python之PySide2安装使用及QT Designer UI设计案例教程
2021/07/26 Python
php访问对象中的成员的实例方法
2021/11/17 PHP
「约定的梦幻岛」作画发布诺曼生日新绘
2022/03/21 日漫
Windows server 2016服务器基本设置
2022/08/14 Servers