Python中实现远程调用(RPC、RMI)简单例子
程序员文章站
2023-11-03 21:30: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)
现在,运行server.py,然后运行client.py,client.py所在的console会输出7。
我们用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)
这其中要输入的uri也就是server2.py生成的uri。通过给pyro4.proxy传递greeting_maker的uri,可以认为和服务器端的greeting_maker建立的连接,然后调用greeting_maker的get_fortune()方法。如果name是letian,那么print greeting_maker.get_fortune(name)的结果是hello, letian.。