在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 相关文章推荐
AJAX for PHP简单表数据查询实例
Jan 02 PHP
JS实现php的伪分页
May 25 PHP
PHP n个不重复的随机数生成代码
Jun 23 PHP
简单实现限定phpmyadmin访问ip的方法
Mar 05 PHP
简单的php数据库操作类代码(增,删,改,查)
Apr 08 PHP
PHP mkdir()无写权限的问题解决方法
Jun 19 PHP
PHP通过内置函数memory_get_usage()获取内存使用情况
Nov 20 PHP
phplot生成图片类用法详解
Jan 06 PHP
PHP、Java des加密解密实例
Apr 27 PHP
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
Oct 20 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
Mar 07 PHP
PHP入门教程之面向对象基本概念实例分析
Sep 11 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(7) php 字符串相关应用
2010/03/05 PHP
php strrpos()与strripos()函数
2013/08/31 PHP
php-perl哈希算法实现(times33哈希算法)
2013/12/30 PHP
php提取字符串中网站url地址的方法
2014/12/03 PHP
Symfony2函数用法实例分析
2016/03/18 PHP
php解决和避免form表单重复提交的几种方法
2016/08/31 PHP
php生成条形码的图片的实例详解
2017/09/13 PHP
PHP+Ajax简单get验证操作示例
2019/03/02 PHP
laravel5.5添加echarts实现画图功能的方法
2019/10/09 PHP
js内置对象 学习笔记
2011/08/01 Javascript
Js获取下拉框选定项的值和文本的实现代码
2014/02/26 Javascript
jquery 自定义容器下雨效果可将下雨图标改为其他
2014/04/23 Javascript
jQuery实现图片文字淡入淡出效果
2015/12/21 Javascript
jQuery Mobile页面返回不需要重新get
2016/04/26 Javascript
JavaScript中日期函数的相关操作知识
2016/08/03 Javascript
JS对象序列化成json数据和json数据转化为JS对象的代码
2017/08/23 Javascript
BootStrap入门学习第一篇
2017/08/28 Javascript
67 个节约开发时间的前端开发者的工具、库和资源
2017/09/12 Javascript
javascript中new Array()和var arr=[]用法区别
2017/12/01 Javascript
vue2 前端搜索实现示例
2018/02/26 Javascript
Nodejs中的JWT和Session的使用
2018/08/21 NodeJs
[58:25]VP vs RNG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python itchat实现微信好友头像拼接图的示例代码
2017/08/14 Python
Python装饰器知识点补充
2018/05/28 Python
Django框架实现的分页demo示例
2019/05/25 Python
Python解析多帧dicom数据详解
2020/01/13 Python
git查看、创建、删除、本地、远程分支方法详解
2020/02/18 Python
Pyspark获取并处理RDD数据代码实例
2020/03/27 Python
台湾SHOPRO购物行家:亚洲首创影视.3C.家电.优质购物平台
2018/05/07 全球购物
美国专业消费电子及摄影器材网站:B&H Photo Video
2019/12/18 全球购物
Java程序员综合测试题
2014/04/25 面试题
计算机应用专业毕业生求职信
2013/10/24 职场文书
公司年会策划方案
2014/05/17 职场文书
学校教师培训工作总结
2015/10/14 职场文书
2016年少先队活动总结
2016/04/06 职场文书
Go并发4种方法简明讲解
2022/04/06 Golang