添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
首页 Qt 基于 Qt 的 XML-RPC 客户端:XML-RPC 协议

基于 Qt 的 XML-RPC 客户端:XML-RPC 协议

0 1.2K
1.2K

XML-RPC 协议是现在大多数 blog 站点支持的标准协议。通过使用该协议,我们可以很方便地使用离线编辑客户端编辑好文章,然后直接上传到 blog 系统进行发布。豆子目前正在进行的一个项目,OrbitsWriter 就是做得类似的工作。尽管完成度不高,但是 XML-RPC 一节已经调通。如果对该项目有任何建议或意见,可以在 GitHub 上找到项目地址。

本文所叙述的实现,即是豆子用在 OrbitsWriter 中的代码。如果需要,完全可以很方便直接从中分离开来。希望这里描述的一种实现,能够对更多的项目有所帮助。

首先来介绍一下 XML-RPC 协议。XML-RPC 是一个通过 Internet 进行的远程过程调用协议。每一个 XML-RPC 消息都是一个 HTTP-POST 请求;请求体则是 XML 格式的。过程在服务器上执行,其返回值同样是 XML 格式。这意味着,我们需要使用 QtNetwork 和 QtXml 两个模块来实现这个客户端。

XML-RPC 协议的过程参数应该是标量,例如数字、字符串、日期等,也可以是复杂的结构体或者数组等。

XML-RPC 请求

下面是一个合法的 XML-RPC 请求:

POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181
<?xml version="1.0"?>
<methodCall>
    <methodName>examples.getStateName</methodName>
    <params>
        <param>
            <value><i4>41</i4></value>
        </param>
    </params>
</methodCall>

请求头

请求头的第一行 URI 的格式并没有指定:可以是空的,可以只有一个斜线(当服务器仅处理 XML-RPC 调用时)。不过,普遍情况应该是服务器处理很多类型的 HTTP 请求。在这种情况下,我们就得利用这个 URI 识别出,这个请求应该由 XML-RPC 处理代码进行处理。在这个例子中,URI 是 /RPC2,也就是说,需要将这个请求分发给 RPC2 这个响应函数。

User-Agent 和 Host 必须指定。

Content-Type 必须是 text/xml。

Content-Length 必须指定,并且必须是正确的。

有效信息格式

有效信息以 XML 的格式发送,其根标签是 <methodCall>

<methodCall> 必须包含一个 <methodName> 子项,类型是一个字符串,包含需要调用的函数名称。这个字符串只能包含可识别字符:大写和小写的 A-Z,数字 0-9,下划线,点号,冒号和斜线。这个名字由服务器进行解释。例如,methodName 可以是包含可执行代码的脚本文件的文件名,可以是数据库表的单元格名,也可以是包含了子目录和子文件的文件夹名。

如果过程调用需要参数, <methodCall> 必须包含一个 <params> 子项。 <params> 则包含若干 <param> 子项,每一个 <param> 都要有一个 <value> 标签。

<value>

<value> 可以是任何标量,类型允许嵌套。合法的子标签如下表所示:

标签 类型 示例
<i4> 或者 <int> 四字节有符号整数 -12
<boolean> 0 (false) 或者 1 (true) 1
<string> 字符串 hello world
<double> 双精度有符号浮点数 -12.214
<dateTime.iso8601> 日期/时间 19980717T14:08:55
<base64> base64 编码的二进制数据 eW91IGNhbid0IHJlYWQgdGhpcyE=

如果不能识别该类型,则当做 string 处理。

<struct>

值类型也可以是 <struct>

<struct> 标签包含若干 <member> ,每一个 <member> 都要有一个 <name> 和一个 <value>

下面是拥有两个元素的 <struct>

<struct>
    <member>
        <name>lowerBound</name>
        <value><i4>18</i4></value>
    </member>
    <member>
        <name>upperBound</name>
        <value><i4>139</i4></value>
    </member>
</struct>

<struct> 可以嵌套。任何 <value> 都可以包含另外的 <struct> 或者其它类型,包括下面介绍的 <array>

<array>

值类型也可以是 <array> <array> 包含一个 <data> 子标签, <data> 则包含若干个 <value>

例如,下面的示例是一个包含了四个元素的数组:

<array>
        <value><i4>12</i4></value>
        <value><string>Egypt</string></value>
        <value><boolean>0</boolean></value>
        <value><i4>-31</i4></value>
    </data>
</array>

<array> 标签没有名字。

正如上面的代码所示,我们可以将不同类型的数据组装成一个数组。

<arrays> 也可以嵌套,任何值都可以包含 <array> 或其它类型,包括 <struct>

XML-RPC 响应

下面是一个合法的 XML-RPC 响应:

HTTP/1.1 200 OK
Connection: close
Content-Length: 158
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:08 GMT
Server: UserLand Frontier/5.1.2-WinNT
<?xml version="1.0"?>
<methodResponse>
    <params>
        <param>
            <value><string>South Dakota</string></value>
        </param>
    </params>
</methodResponse>

响应格式

第一行,除非有其它服务器错误,返回值总是 200 OK。

Content-Type 是 text/xml。Content-Length 必须指定,并且是正确的。

响应体是一个 XML 结构,根标签是 <methodResponse> ,包含一个 <params> 标签,该标签又包含一个 <value>

<methodResponse> 也可能包含一个 <fault> 标签,这个 <fault> 包含一个 <value> ,该标签是一个 <struct> ,包含两个元素: <faultCode> <int> 类型以及 <faultString> <string> 类型。

<methodResponse> 不允许同时包含 <fault> <params>

<fault> 示例

HTTP/1.1 200 OK
Connection: close
Content-Length: 426
Content-Type: text/xml
Date: Fri, 17 Jul 1998 19:55:02 GMT
Server: UserLand Frontier/5.1.2-WinNT
<?xml version="1.0"?>
<methodResponse>
    <fault>
        <value>
            <struct>
                <member>
                    <name>faultCode</name>
                    <value><int>4</int></value>
                </member>
                <member>
                    <name>faultString</name>
                    <value><string>Too many parameters.</string></value>