pythontty 2014-04-28
远程调用使得调用远程服务器的对象、方法的方式就和调用本地对象、方法的方式差不多,因为我们通过网络编程把这些都隐藏起来了。远程调用是分布式系统的基础。
远程调用一般分为两种,远程过程调用(RPC)和远程方法调用(RMI)。
RPC
RPC属于函数级别的远程调用,其多是通过HTTP传输数据,数据形式有XML、JSON、序列化数据等。在此,用python做一个xml-rpc的示例。 先给服务器端server.py:
代码如下:
from SimpleXMLRPCServer import SimpleXMLRPCServer def add(x, y): return x + y if __name__ == '__main__': s = SimpleXMLRPCServer(('127.0.0.1', 8080)) s.register_function(add) s.serve_forever() s是一个绑定了本地8080端口的服务器对象,register_function()方法将函数add注册到s中。serve_forever()启动服务器。 再给个客户端client.py: from xmlrpclib import ServerProxy if __name__ == '__main__': s = ServerProxy("http://127.0.0.1:8080") print s.add(3,4)
我们用wireshark看一下这期间传递的数据是什么样子的,请求的数据:
代码如下:
<?xml version='1.0' ?> <methodCall> <methodName> add </methodName> <params> <param> <value> <int> 3 </int> </value> </param> <param> <value> <int> 4 </int> </value> </param> </params> </methodCall>
代码如下:
<?xml version='1.0' ?> <methodResponse> <params> <param> <value> <int> 7 </int> </value> </param> </params> </methodResponse>
RMI
RMI意为远程方法调用,粒度比RPC要大,因为它的基本单位是对象。其大致思路是这样的:创建RMI服务器对象,将实例化的某个对象以指定的服务名称(也可以是多个对象,但是服务名称不应相同)注册到RMI服务器对象中,之后启动RMI服务器。服务器等待客户端发送的数据(包括服务名称、函数名、参数),将处理结果返回给客户端。 Pyro4是一个基于python的RMI实现,下面我们用Pyro4创建一个RMI服务器,请看server2.py:
代码如下:
import Pyro4 class GreetingMaker(object): def get_fortune(self, name): return "Hello, {0}. \n" .format(name) greeting_maker=GreetingMaker() daemon=Pyro4.Daemon() uri=daemon.register(greeting_maker) print "Ready. Object uri =", uri daemon.requestLoop() uri变量是Pyro4用自己的方法为greeting_maker对象生成的uri,其中包括套接字以及为greeting_maker生成的唯一的id。这个id相当于服务名称,当然也可以指定更易懂的服务名称。下面是客户端client2.py: import Pyro4 uri=raw_input(" Pyro uri : ").strip() name=raw_input("Your name: ").strip() greeting_maker=Pyro4.Proxy(uri) print greeting_maker.get_fortune(name)