一.简介

XML-RPC的全称是XML Remote Procedure Call,即XML远程方法调用。

它是一套允许运行在不同操作系统、不同环境的程序实现基于Internet过程调用的规范和一系列的实现。 这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式。 XML-RPC的定义尽可能的保持了简单,但同时能够传送、处理、返回复杂的数据结构。

XML-RPC是使用HTTP协议做为传输协议的RPC(远程方法调用)机制,使用XML文本的方式传输命令和数据。
一个RPC系统,必然包括2个部分:
  1.RPC Client,用来向RPC Server调用方法,并接收方法的返回数据;
  2.RPC Server,用于响应RPC Client的请求,执行方法,并回送方法执行结果。
  RPC是Remote Procedure Call的缩写,翻译成中文就是远程方法调用,是一种在本地的机器上调用远端机器上的一个过程(方法)的技术,这个过程也被大家称为“分布式计算”,是为了提高各个分立机器的“互操作性”而发明出来的技术。

XML-RPC的可用版本 
XML-RPC client和XML-RPC server都有很多版本的实现。一般而言,一个实现版本都会同时实现client/server。但由于都满足xml rpc规范,从理论上讲,任何一个版本的XML-RPC client实现与任何一个版本的XML-RPC server都能配套使用。
更进一步,由于XML-RPC以XML文本的方式,使用http协议传输,所以与编程语言无关。例如:XML-RPC client的已实现版本包括了:perl,php,python,c/c++,java,等等;XML-RPC server的实现语言包括perl,java,等。
同一种编程语言所实现的版本也不止一个。例如java版的实现有:

  Marque的XML-RPC现在已经和Redstone XML-RPC Library合并(http://xmlrpc.sourceforge.net/)

  Apache的XML-RPC实现,这个项目隶属于apache web service项目,故URL地址开头为ws.apache(http://ws.apache.org/)下载链接http://archive.apache.org/dist/ws/有些时候直接点进项目去,无法通过镜像下载,这时候就可以访问http://archive.apache.org/通过这个链接可以下载apache的任何资源。话说apache真是伟大呀!

  这个网页讲的真是太好了,虽然是英语:http://www.tutorialspoint.com/xml-rpc/xml_rpc_quick_guide.htm

  这个网页讲的有点深:http://www.ibm.com/developerworks/cn/webservices/1211_zhusy_rpc/

二.python实现

牛人太多,我已无言。python实现http://blog.csdn.net/abcjennifer/article/details/38393185

创建服务器,构造方法,注册方法

from SimpleXMLRPCServer import SimpleXMLRPCServer
def is_even(n):
    return n%2 == 0
server = SimpleXMLRPCServer(("localhost", 8000))#确定URL和端口
print "Listening on port 8000..."
server.register_function(is_even, "is_even") #注册is_even函数
server.serve_forever()#启动服务器,并使其对这个连接可用

创建客户端,请求方法

import xmlrpclib
proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
print "3 is even: %s" % str(proxy.is_even(3))#客户端调用XML-RPC函数
print "100 is even: %s" % str(proxy.is_even(100))

三.xmlrpc++是C++版的xml-rpc接口实现

四.java大法好,一统天下

apache的XML-RPC似乎发生了很大改变,变得极为严谨。

下面的代码分为服务器端和客户端两部分,故意用了用一句话编程。读之给人一种一气呵成,气贯长虹质感。功能是:服务器端有两个函数add和sub,客户端请求其中之一并传入两个int类型的参数,返回int类型的结果并输出。

服务器端代码:

class RPCServer {
    public static void main(String[] args) throws IOException {
        WebServer server = new WebServer(8080);
        server.getXmlRpcServer().setHandlerMapping(new XmlRpcHandlerMapping() {

            @Override
            public XmlRpcHandler getHandler(String handlerName)
                    throws XmlRpcNoSuchHandlerException, XmlRpcException {
                switch (handlerName) {
                    case "add" :
                        return new XmlRpcHandler() {

                            @Override
                            public Object execute(XmlRpcRequest arg)
                                    throws XmlRpcException {
                                int x = (int) arg.getParameter(0),
                                        y = (int) arg.getParameter(1);
                                return x + y;
                            }
                        };
                    case "sub" :
                        return new XmlRpcHandler() {

                            @Override
                            public Object execute(XmlRpcRequest arg)
                                    throws XmlRpcException {
                                int x = (int) arg.getParameter(0),
                                        y = (int) arg.getParameter(1);
                                return x - y;
                            }
                        };
                    default :
                        return null;
                }
            }
        });
        server.start();
    }
}

下面是客户端代码

class RPCClient {
    public static void main(String[] args) throws XmlRpcException {
        XmlRpcClient client = new XmlRpcClient();
        int ans = (int) client.execute(new XmlRpcRequest() {
            int x = 3, y = 6;
            @Override
            public int getParameterCount() {
                return 2;
            }

            @Override
            public Object getParameter(int x) {
                if (x == 0)
                    return this.x;
                else
                    return this.y;
            }

            @Override
            public String getMethodName() {
                return "add";
            }

            @Override
            public XmlRpcRequestConfig getConfig() {
                XmlRpcClientConfigImpl x = new XmlRpcClientConfigImpl();
                try {
                    x.setServerURL(new URL("http://localhost:8080"));
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                return x;
            }
        });
        System.out.println(ans);
    }
}

五.关于metaweblog协议

这个协议应用了XML-RPC,是各大博客统一支持的接口,供用户使用。百度metaweblog会出来一堆的,用这几个函数接口就足以访问博客了。下面以博客园的接口为例简要介绍:

三个大类九大函数七大结构体:

三个大类是谁?blogger(2个函数),metaWeblog(6个函数),wp(1个函数)

九大函数是谁?

•blogger.deletePost 删除随笔
•blogger.getUsersBlogs获取我的博客,我可能有多个博客
•metaWeblog.editPost修改随笔
•metaWeblog.getCategories获取随笔类别
•metaWeblog.getPost获取随笔
•metaWeblog.getRecentPosts获取最近随笔
•metaWeblog.newMediaObject新建多媒体对象,其实就是上传文件,在博客园里面只能上传图片,返回图片的url,这样这文章中就可以使用这个url了。
•metaWeblog.newPost新建随笔

•wp.newCategory这个函数似乎是博客园独有的,可以添加分类

这九大函数根据名称就能看出来分为三大家子,其中wp这一家只有一个”新建类别“函数,blogger这一家有弟兄俩,这两个函数都需要appKey,这appKey其实不是必要的,博客园中用不到;metaWeblog是最主要的,包括对随笔的增改查三种操作,其中查又分为两种操作:根据postid查询博客;查询最近博客。metaWeblog还包括一个上传文件操作。

七个结构体

BlogInfo描述博客的id,url,博客名等信息;

Post描述随笔的发布日期,题目,类别,具体内容等信息;

CategoryInfo描述类别信息;

FileData描述如何传输文件,包括文件名及文件内容,其中文件内容采用base64编码,上传到服务器后返回一个url,FileData有三个成员变量

  bits:文件内容,byte[]类型,推荐使用java.nio一句话的事:Files.readAllBytes(Paths.get("shq.jpg")):byte[]

  name:文件名,后缀必须是\.jpg|\.gif|\.png|\.jpeg之一,也就是说只允许上传图片

  type:文件类型(不需要设置,如果设置了,容易出错,返回500服务器内部错误),服务器自己会解析什么类型,无须告知。

URLData只包含一项URL,写的博客是一个html,里面嵌套着图片,图片以结构体的形式FileData用metaWeblog.newMediaObject上传到服务器,返回一个url,这样就可以在html中使用这个url了。

Enclosure包括长度,类型,URL三项。

Source包含url及名称两项

以上内容在博客园里可以找到:

方式一:管理>设置选项底部

方式二:在我的首页,ctrl+u查看网页源代码,<header>里面有一个RSD(really simple discovery),进入这个链接,它是一个XML,里面包含了博客园的weblog入口。

顺道说说RSS和RSD。

RSS:really simple syndication简易信息聚合,为了人们快速获取有效信息。

RSD:really simple discovery简易入口,为了人们快速找到网络服务入口。

这两者都是特定领域协议。

六.XML-RPC的数据类型

是不是顺序有点乱,觉得应该把这一部分放在前面。其实都行,学习就需要回环往复,由深入浅又由浅入深,没有必要按部就班,只要会了就行。

6种基本数据类型,2种组合数据类型。XML-RPC说:一切皆value。所以一共有八种value。

<value><int>2323</int></value>
<value><double>23.23<double></value>
<value><boolean>1或者0</boolean></value>
<value><string>weidiao</string></value>
<value><dateTime>20021125T02:20:04</dateTime></value>格式显而易见:yyyyMMddThh:mm:ss
<value><base64>ASDFASD9823</base64></value>将任意二进制数据转换成base64编码方式。
<value><array><data>里面可以放多个value</data></array></value>我认为data这个标签有点多余
<value><struct>这里可以放多个member,每一个member都是一个name-value-pair</struct></value>

Basic Data Types in XML-RPC

Type Value Examples
int or i4 32-bit integers between - 2,147,483,648 and 2,147,483,647.

<int>27</int>

<i4>27</i4>

double 64-bit floating-point numbers

<double>27.31415</double>

<double>-1.1465</double>

Boolean true (1) or false (0)

<boolean>1</boolean>

<boolean>0</boolean>

string ASCII text, though many implementations support Unicode

<string>Hello</string>

<string>bonkers! @</string>

dateTime.iso8601 Dates in ISO8601 format: CCYYMMDDTHH:MM:SS

<dateTime.iso8601>

20021125T02:20:04

</dateTime.iso8601>

<dateTime.iso8601>

20020104T17:27:30

</dateTime.iso8601>

base64 Binary information encoded as Base 64, as defined in RFC 2045

<base64>SGVsbG8sIFdvcmxkIQ==</base64>

两种组合数据类型:数组和结构体。数组表示了一种序列化信息,数组可以包含多种数据类型;结构体其实相当于映射,是键值对,是属性集,是关联数组。

基本数据类型在xml中表示如下:<value><type>xxxx</type></value>。除了string类型可以省略<type>标签外,其余五种基本数据类型必须明确注明数据类型(这一点就不要记了,统一处理,<value></value>必须注明数据类型)。

<value>
   <array>
      <data>
         <value><string>This </string></value>
         <value><string>is </string></value>
         <value><string>an </string></value>
         <value><string>array.</string></value>
      </data>
   </array>
</value>

数组中的元素类型可以有多种:

<value>
   <array>
      <data>
         <value><int>7</int></value>
         <value><string>dfdfdf</string></value>
         <value><int>-91</int></value>
         <value><int>42</int></value>
      </data>
   </array>
</value>

数组也可以嵌套的,很显然数组相当于value的一种

<value>
   <array>
      <data>

         <value>
            <array>
               <data>
                  <value><int>10</int></value>
                  <value><int>20</int></value>
                  <value><int>30</int></value>
               </data>
            </array>
         </value>

         <value>
            <array>
               <data>
                  <value><int>15</int></value>
                  <value><int>25</int></value>
                  <value><int>35</int></value>
               </data>
            </array>
         </value>

      </data>
   </array>
</value>
结构体的长相是这样的:
<value>
   <struct>
      <member>
         <name>givenName</name>
         <value><string>Joseph</string></value>
      </member>

      <member>
         <name>familyName</name>
         <value><string>DiNardo</string></value>
      </member>

      <member>
         <name>age</name>
         <value><int>27</int></value>
      </member>
   </struct>
</value>

七.发出请求
请求的格式是http请求头部+xml的具体数据内容,通过post方式发送到服务器。
其中xml内容包括两大部分:方法名及参数,一旦进入<param></param>标签,就跟上面那些数据类型一样一样的了。

<?xml version="1.0"?>
<methodCall>
   <methodName>circleArea</methodName>
      <params>
         <param>
            <value><double>2.41</double></value>
         </param>
      </params>
</methodCall>

八.回复的格式

包括两部分:http头部+xml具体内容,跟发送时没多大区别。如你所见,既然有http头部,那就完全可以保存cookie。

HTTP/1.1 200 OK
Date: Sat, 06 Oct 2001 23:20:04 GMT
Server: Apache.1.3.12 (Unix)
Connection: close
Content-Type: text/xml
Content-Length: 124

<?xml version="1.0"?>
<methodResponse>
   <params>
      <param>
         <value><double>18.24668429131</double></value>
      </param>
   </params>
</methodResponse>

谁又能保证回复是一定正确的呢?服务器把错误信息反馈给用户.

<?xml version="1.0"?>
<methodResponse>
   <fault>
      <value>
         <struct>
            <member>
               <name>code</name>
               <value><int>26</int></value>
            </member>

            <member>
               <name>message</name>
               <value><string>No such method!</string></value>
            </member>

         </struct>
      </value>
   </fault>
</methodResponse>

既然知道了发送和接受的数据格式,那么我们完全可以自己实现这个XML-RPC协议,不就是向服务器post字符串吗?post的时候有多种方式,可以同步可以异步,可以用原生的URLConnection也可以用封装过的HTTPClient。
于是问题转化为对xml串的生成和解析。xml的生成和解析也有很多库。完全可以自主开发出一套XML-RPC库。

九.接下来看什么

WSDL网络服务描述语言:基于XML描述了web服务的功能,消息格式以及协议细节.

SOAP:基于XML,用于程序之间通过http进行交流

十.内省方法

introspect
一个好的事物必然能够系统地告诉人们它的一切,而不是藏着掖着。任何好的开源组件都必然对应详尽的文档。
XML-RPC规定了三个保留方法用来内省服务器。
什么叫内省(xing),就是朝里看,对里面进行探测。
比如,根据数据库中的表自动生成实体类(PO,persistent object)叫内省;
在fastjson中把javaBean映射成map对象,需要探知Bean中的全部属性和get,set方法,这也叫内省;
使用XML-RPC时,调用这三个方法,就可以对服务器提供的可用方法有一个整体的认识。
人类都有一种感觉:如果对一样事物没有全局的把控,就不踏实。其实能够在这种不踏实的感觉下勇猛前行者,最终才能够变得踏实,要有一种反复咀嚼的精神。
system.listMethods 无参函数,返回全部方法
system.methodSignature 传入函数名称
system.methodHelp 传入函数名称
第一个函数,返回可用方法列表;第二个函数,返回方法签名;第三个函数返回函数详情。
至于返回值是什么类型的,可以通过java中的Object#getClass() 反射得到类型名称。

十一.XML-RPC的替代者

hessian基于二进制传递数据,速度快,但跨平台性比不上纯字符串格式的快.

JSON-RPC基于json串传递数据

XML-RPC远程方法调用的更多相关文章

  1. 简单实现Java的RMI——远程方法调用

    一.RMI简介: 说到RMI就不得不说RPC了. RPC:(Remote Procedure Call),远程过程调用. RMI(Remote Method Invocation),远程方法调用. R ...

  2. Java APi 之 RMI远程方法调用

    一.什么是RPC RPC全称是remote procedure call,即远程过程调用.它是一种协议,用于从远程计算机上请求服务. 例如有两台服务器A和B,A上的应用想要调用B上应用的方法,但是他们 ...

  3. [转]Java远程方法调用

    Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远 ...

  4. SpringBoot里使用RMI进行远程方法调用

    一.Java RMI定义 Java RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程 ...

  5. RMI远程方法调用

    RMI远程方法调用:适用于 客户端 调用 服务器 内的方法:(Kotlin 语言编写) 如果业务为二个服务器之间的通信,还是得用消息队列的形式,因为RMI 不适合 双向 调用 下面介绍RMI 的使用方 ...

  6. 【Java Web开发学习】远程方法调用RMI

    Java RMI 远程方法调用Remote Method Invocation 转载:http://www.cnblogs.com/yangchongxing/p/9078061.html 1.创建远 ...

  7. Java RMI 远程方法调用

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  8. Java RMI远程方法调用

    RMI(远程接口调用) 1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程引用层(Remote Reference Layer)和传 ...

  9. SpringRMI远程方法调用

    Spring为各种远程访问技术的集成提供了工具类. 该小段引用自 http://www.open-open.com/lib/view/open1408957290478.html Spring远程支持 ...

随机推荐

  1. CentOS 6.3下配置LVM(逻辑卷管理)

    一.简介 LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的灵 ...

  2. Elasticsearch 安装中文分词

    github地址:https://github.com/medcl/elasticsearch-analysis-ik 注意版本要对应,否则编译完成后elasticsearch不能正常启动 下载文件, ...

  3. 2015 Selenium大会

    9月8号到10号三天在俄勒冈州的波特兰召开了Selenium Conference 2015,分享的演讲很多,视频也放出来了,做了下搬运工,传到优酷 简介: A conference that bri ...

  4. python 使用pip安装第三方模块

    part 1:使用方法: 1.pip install somePackage picture 1 2.pip show somePackage 例如:pip show pip 弹出关于该模块的信息 p ...

  5. Java中的四套读写方案

    一.字节流读写方案 FileInputStream:字节流方式读取文本文件 FileoutputStream:字节流写入硬盘 二.字符流读写方案 FileReader:字符流读取文本 FileWrit ...

  6. fragment的切换(解决REPLACE的低效)

    在项目中切换Fragment,一直都是用replace()方法来替换Fragment.但是这样做有一个问题,每次切换的时候Fragment都会重新实列化,重新加载一次数据,这样做会非常消耗性能用用户的 ...

  7. Json 基于jQuery+JSON的省市联动效果

    helloweba.com 作者:月光光 时间:2012-09-12 21:57 标签: jQuery  JSON  Ajax  省市联动     省市区联动下拉效果在WEB中应用非常广泛,尤其在一些 ...

  8. 一种Docker image镜像的取代方案

    在http://openvz.org/Download/templates/precreated中有很多压缩的镜像文件,可以将这些文件下载后采用import方式使用镜像,也可以采用我原来的博文:doc ...

  9. C语言--指向多维数组的指针和指针数组

    #include <stdio.h> //void show(char *p[]); ]); int main(){ ][]={","abc","x ...

  10. Java 日志性能优化

    1. 选择合理的日志级别.合理控制日志内容 2. 控制日志的输出内容和格式 logger.debug("Entry number: " + i + " is " ...