在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作的文本留言本的例子(一)
Oct 09 PHP
php设计模式 Prototype (原型模式)代码
Jun 26 PHP
PHP CodeIgniter框架的工作原理研究
Mar 30 PHP
学习php设计模式 php实现命令模式(command)
Dec 08 PHP
php插入含有特殊符号数据的处理方法
Nov 24 PHP
php 微信开发获取用户信息如何实现
Dec 13 PHP
yii2使用GridView实现数据全选及批量删除按钮示例
Mar 01 PHP
PHP实现一个轻量级容器的方法
Jan 28 PHP
PHP实现文字写入图片功能
Feb 18 PHP
PHP常见过waf webshell以及最简单的检测方法
May 21 PHP
Laravel 框架路由原理与路由访问实例分析
Apr 14 PHP
如何在PHP中使用数组
Jun 09 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中用文本文件做数据库的实现方法
2008/03/27 PHP
php返回当前日期或者指定日期是周几
2015/05/21 PHP
在WordPress中使用PHP脚本来判断访客来自什么国家
2015/12/10 PHP
PHP快速推送微信模板消息
2017/04/14 PHP
用js判断用户浏览器是否是XP SP2的IE6
2007/03/08 Javascript
JQery jstree 大数据量问题解决方法
2010/03/09 Javascript
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件
2011/12/21 Javascript
javascript学习笔记(七) js函数介绍
2012/06/19 Javascript
js window.print实现打印特定控件或内容
2013/09/16 Javascript
javascript类型转换示例
2014/04/29 Javascript
使用Plupload实现直接上传附件至七牛云存储
2014/12/26 Javascript
js实现最短的XML格式化工具实例
2015/03/12 Javascript
jQuery实现时尚漂亮的弹出式对话框实例
2015/08/07 Javascript
bootstrap modal弹出框的垂直居中
2016/12/14 Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
2017/06/03 Javascript
手动用webpack搭建第一个ReactApp的示例
2018/04/11 Javascript
浅谈vue项目打包优化策略
2018/09/29 Javascript
vue监听用户输入和点击功能
2019/09/27 Javascript
ES6学习笔记之字符串、数组、对象、函数新增知识点实例分析
2020/01/22 Javascript
jQuery实现查看图片功能
2020/12/01 jQuery
在Django的模型和公用函数中使用惰性翻译对象
2015/07/27 Python
Python编程argparse入门浅析
2018/02/07 Python
Python实现ping指定IP的示例
2018/06/04 Python
Win10下python3.5和python2.7环境变量配置教程
2018/09/18 Python
python中复数的共轭复数知识点总结
2020/12/06 Python
python中的列表和元组区别分析
2020/12/30 Python
css3截图_动力节点Java学院整理
2017/07/11 HTML / CSS
北美三大旅游网站之一:Travelocity
2017/08/12 全球购物
高级运动鞋:GREATS
2019/07/19 全球购物
公司司机岗位职责
2014/02/07 职场文书
绿色学校实施方案
2014/03/31 职场文书
2014年信息中心工作总结
2014/12/17 职场文书
小学生毕业评语
2014/12/26 职场文书
关于战胜挫折的名言警句大全!
2019/07/05 职场文书
导游词之阳朔遇龙河
2019/12/16 职场文书