XML-RPC 和 XML-RPC 服务器类
CodeIgniter 的 XML-RPC 类允许你发送请求到另一个服务器, 或者建立一个你自己的XML-RPC服务器来接受请求.
什么是XML-RPC?
这是一个非常简单的两台计算机使用XML通过互联网进行通信的方法. 一台计算机 , 我们称之为 客户端 , 发送一个XML-RPC 请求 给另外一台计算机 , 我们称之为 服务器. 当服务器收到请求并加以处理,然后将 结果 返回给客户端.
例如,使用 MetaWeblog 的 API(应用程序接口) , 一个XML-RPC客户端(通常是桌面发布工具)会发送一个请求到运行在你网站的XML-RPC服务端. 这个请求有可能是要发布一篇新的网志,或者是要修改已存在的网志. 当XML-RPC服务器接收到请求,将检验请求并且决定调用何种类/方法来处理请求.一旦处理完毕,服务器将返回一个响应信息.
如果要查看更详细的规范,你可以浏览 XML-RPC 网站.
初始化类
像CodeIgniter的大多数类一样, XML-RPC 和 XML-RPCS 类 在你的控制器中调用 $this->load->library 方法来进行初始化:
使用以下代码载入XML-RPC类库:
$this->load->library('xmlrpc');
一旦XML-RPC类被载入, XML-RPC 库的对象就可以使用了: $this->xmlrpc
使用下面的方法载入 XML-RPC 服务器类:
一旦加入,可以通过 _$this->xmlrpcs_ 使用 xml-rpcs 库对象: _$this->xmlrpcs_ **注意:** 使用 XML-RPC 服务器,必须同时载入 XML-RPC 类和 XML-RPC 服务器类。 ## 发送 XML-RPC 请求 发送一个请求到 XML-RPC 服务器,需指定如下信息: - 服务器的 URL - 你要调用的服务器上的方法。 - The _请求_ 数据 (说明见下面). 下面是一个简单的例子,它发送一个简单的 Weblogs.com ping 到[Ping-o-Matic](http://pingomatic.com/)
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
$this->load->library('xmlrpc');
$this->xmlrpc->server('http://rpc.pingomatic.com/', 80);
$this->xmlrpc->method('weblogUpdates.ping');
$request = array('My Photoblog', 'http://www.my-site.com/photoblog/');
$this->xmlrpc->request($request);
if ( ! $this->xmlrpc->send_request())
{
echo $this->xmlrpc->display_error();
}
说明
以上代码初始化XML-RPC类,设置了服务器的URL和要调用的方法(weblogUpdates.ping). 请求(在此例中为你网站的标题和URL)被放在一个数组中使用 request() 函数传输、编译。最后,整个请求发出,如果send_request()方法返回 false,我们将显示XML-RPC 服务器发回的错误信息。
请求剖析
一个 XML-RPC 请求只是你发送到 XML-RPC 服务器的数据。请求中的每个数据片断也被称为请求参数。在上面的示例中,有两个参数:你网站的URL和标题。当 XML-RPC 服务器接到你的请求,服务器会寻找请求参数。
请求参数必须放在数组中传输,每个参数可以是七种数据类型中的任一种(字符串,数字,日期,等等)。如果你的参数是字符串外的其它类型,则必须在请求数组中包含数据类型。
下面是一个包含三个参数的简单数组示例:
如果你使用除字符串以外的其它类型,或有几种不同的数据类型,你需要将每个参数单独放到一个数组中,并在数组第二个位置给出数据类型。
$request = array('John', 'Doe', 'www.some-site.com');
$this->xmlrpc->request($request);
[数据类型](#datatypes) 中包括完成的数据类型列表。 ## 创建 XML-RPC 服务器 XML-RPC 服务扮演着交通警察的角色,等待进入的请求,并将它们转到恰当的函数进行处理。 要创建自己的 XML-RPC 服务器,包括在接受请求的控制器中初始化 XML-RPC 服务器类,然后设置一个指向映射数组以便收到的请求可以被发送到恰当的类与方法来处理。 下面用一个例子来说明:
$request = array (
array('John', 'string'),
array('Doe', 'string'),
array(FALSE, 'boolean'),
array(12345, 'int')
);
$this->xmlrpc->request($request);
上面的例子中有一个包含两个服务器允许的特定请求方法的数组。这些被允许的方法在数组的左边,当收到其中任何一个方法时,它会被立刻映射到数组右边所列出的类与方法。 '_Object_'是一个特殊的键,它是你传递的类的实例,这个键是必要的,尤其是当你映射到的方法不是 Codeigniter 超类的一部分。 换句话说,如果 XML-RPC 客户端发送一个请求到 _new_post_ 方法,你的服务器会加载 _My_blog_ 类并调用 _new_entry_ 函数。如果这个请求是到 _update_post_ 方法的,那么你的服务器会加载 _My_blog_ 类并调用 _update_entry_ 函数。 上面例子中的函数名是任意的。你可以决定这些函数在你的服务器上叫什么名字,如果你使用的是标准的 API,比如:Blogger 或者 MetaWeblog 的 API,你必须使用标准的函数名。 这里还有两个附加的配置项,可以在服务器类初始化时配置使用。_debug_ 设为 TRUE 以便调试,_xss_clean_ 可被设置为 FALSE 以避免数据被安全类库的 _xss_clean_ 函数过滤。 ## 处理服务器请求 当 XML-RPC 服务器收到请求并加载类与方法来处理时,服务器会传递一个包含客户端发送数据的对象到指定的方法。 在上面的例子中,如果请求的是 _new_post_ 方法,服务器请求的类与方法会像这样:
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
$config['functions']['new_post'] = array('function' => 'My_blog.new_entry'),
$config['functions']['update_post'] = array('function' => 'My_blog.update_entry');
$config['object'] = $this;
$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();
_$request_ 变量是一个由服务端汇集的对象,包含由 XML-RPC 客户端发送来的数据。使用该对象可以让你访问到 _request parameters_ 以便处理请求。请求处理完成后,发送一个 _Response_ 返回给客户端。 下面是一个较为实际的例子,使用 Blogger 的 API。Blogger API 中的一个方法是 _getUserInfo()_,使用该方法 XML-RPC 客户端可以发送用户名和密码到服务器,在服务器返回的数据会包含该特定用户的信息(昵称,用户 ID,Email 地址等等)。下面是处理函数可能的样子:
class My_blog extends CI_Controller {
function new_entry($request)
{
}
}
class My_blog extends CI_Controller {
function getUserInfo($request)
{
$username = 'smitty';
$password = 'secretsmittypass';
$this->load->library('xmlrpc');
$parameters = $request->output_parameters();
if ($parameters['1'] != $username AND $parameters['2'] != $password)
{
return $this->xmlrpc->send_error_message('100', 'Invalid Access');
}
$response = array(array('nickname' => array('Smitty','string'),
'userid' => array('99','string'),
'url' => array('http://yoursite.com','string'),
'email' => array('jsmith@yoursite.com','string'),
'lastname' => array('Smith','string'),
'firstname' => array('John','string')
),
'struct');
return $this->xmlrpc->send_response($response);
}
}
注意:
output_parameters() 函数会检索一个由相应客户端发送的索引过的请求参数数组。上面的例子中输出参数将会是用户名和密码。
如果客户端发送的用户名和密码无效的话,错误信息会通过 send_error_message() 函数返回。
如果操作成功,客户端会收到包含用户信息的反馈数组。
格式化反馈信息
就像 Requests, Responses 必须被格式化为数组。然而不同于请求信息,反馈信息是只包含一个项的数组。该项可以是一个包含很多其他数组的的数组,但是只有一个主数组索引,下面是一个反馈信息大概的样子:
但是反馈信息通常包含多个分块信息。要做到这样,我们必须把各分块信息放到他们自己的数组中,这样主数组就始终只有一个数据项。这里是一个例子来展示如何达成这样的效果:
$response = array('Response data', 'array');
注意:上面的数组被格式化为 _struct_,这是反馈信息最常见的数据类型。 如同请求信息一样,反馈信息可以是七种数据类型中的一种,参见 [数据类型](#datatypes) 一节。 ## 发送出错反馈 如果你需要发送给客户端一个出错反馈,你会使用到下面的代码:
$response = array (
array(
'first_name' => array('John', 'string'),
'last_name' => array('Doe', 'string'),
'member_id' => array(123435, 'int'),
'todo_list' => array(array('clean house', 'call mom', 'water plants'), 'array'),
),
'struct'
);
第一个参数是出错编号,第二个参数是出错信息。 ## 创建你自己的客户端与服务端 为了帮助理解这些,让我们创建两个控制器来演示 XML-RPC 的客户端和服务端。你将用客户端来发送一个请求到服务端并从服务端收到一个反馈。 ### 客户端 使用编辑器创建一个控制器,起名为 _xmlrpc_client.php_。在这个控制器中,粘贴以下的代码并保存到 applications/controllers/ 目录:
return $this->xmlrpc->send_error_message('123', 'Requested data not available');
注意:在上面的代码中我们使用了 "url" 辅助函数,你可以在[辅助函数]($9e16575ba7b69744.md)页面找到更多信息。 ### 服务端 使用编辑器创建一个控制器,起名为 _xmlrpc_server.php_。在这个控制器中,粘贴一下代码并保存到 applications/controllers/ 目录:
<?php
class Xmlrpc_client extends CI_Controller {
function index()
{
$this->load->helper('url');
$server_url = site_url('xmlrpc_server');
$this->load->library('xmlrpc');
$this->xmlrpc->server($server_url, 80);
$this->xmlrpc->method('Greetings');
$request = array('How is it going?');
$this->xmlrpc->request($request);
if ( ! $this->xmlrpc->send_request())
{
echo $this->xmlrpc->display_error();
}
else
{
echo '<pre>';
print_r($this->xmlrpc->display_response());
echo '</pre>';
}
}
}
?>
<?php
class Xmlrpc_server extends CI_Controller {
function index()
{
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
$config['functions']['Greetings'] = array('function' => 'Xmlrpc_server.process');
$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();
}
function process($request)
{
$parameters = $request->output_parameters();
$response = array(
array(
'you_said' => $parameters['0'],
'i_respond' => 'Not bad at all.'),
'struct');
return $this->xmlrpc->send_response($response);
}
}
?>
试试吧!
现在像下面的链接这样访问你的站点:
现在你应该能看到你发送到服务端的信息,并且被返回给了你。 在客户端,你发送了一条消息 ("How's is going?") 到服务端,随着一个请求发送到 "Greetings" 方法。服务端收到这个请求并映射到 "process" 函数,然后把反馈信息返回。 ## 在请求参数中使用关联数组 如果你希望在你的方法参数中使用关联数组,那么你需要使用 struct 数据类型:
example.com/index.php/xmlrpc_client/
你可以在服务端处理请求信息时检索关联数组。
$request = array(
array(
// Param 0
array(
'name'=>'John'
),
'struct'
),
array(
// Param 1
array(
'size'=>'large',
'shape'=>'round'
),
'struct'
)
);
$this->xmlrpc->request($request);
$parameters = $request->output_parameters();
$name = $parameters['0']['name'];
$size = $parameters['1']['size'];
$shape = $parameters['1']['shape'];
XML-RPC 函数参考
$this->xmlrpc->server()
设置发送给服务器端的XML-RPC的url和端口参数:
$this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);
$this->xmlrpc->timeout()
设置一个超时时间(以秒计算):
$this->xmlrpc->timeout(6);
$this->xmlrpc->method()
设置XML-RPC服务器接受的请求方法:
参数名称是 _method_. ## $this->xmlrpc->request() 设置发送给XML-RPC服务器的数组数据:
$this->xmlrpc->method('method');
$request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
$this->xmlrpc->request($request);
$this->xmlrpc->send_request()
请求发送函数. 函数使用之前设置的参数去发起请求XML-RPC服务,成功则返回布尔值TRUE,失败则返回布尔值.
$this->xmlrpc->set_debug(TRUE);
开始调试模式, 开启后,程序将输出错误、警告等信息,以帮助开发者更快的找到问题所在。
$this->xmlrpc->display_error()
当请求失败后,返回错误信息。
echo $this->xmlrpc->display_error();
$this->xmlrpc->display_response()
远程服务器接收请求后,返回的数据通常是一个关联数组。
$this->xmlrpc->display_response();
$this->xmlrpc->send_error_message()
此函数允许你从服务器发送一个错误消息到客户端.第一个参数是错误编号,第二个参数是错误信息。
return $this->xmlrpc->send_error_message('123', 'Requested data not available');
$this->xmlrpc->send_response()
从服务器发送返回数据到客户端,可以用下面的方法发送一个合法的数组。
$response = array( array( 'flerror' => array(FALSE, 'boolean'), 'message' => "Thanks for the ping!" ) 'struct');return $this->xmlrpc->send_response($response);
数据类型
参考 XML-RPC 规格说明 您可通过XML-RPC发送以下几种数据类型:
- int or i4
- boolean
- string
- double
- dateTime.iso8601
- base64
- struct (contains array of values)
- array (contains array of values)
翻译贡献者:Hex, huanxiangwu, huboo, ianyang, Jacklee, shishirui, sydcurie, wanglinqiang