說白了,遠程調用就是將對象名、函數名、參數等傳遞給遠程服務器,服務器將處理結果返回給客戶端python
遠程調用使得調用遠程服務器的對象、方法的方式就和調用本地對象、方法的方式差很少,由於咱們經過網絡編程把這些都隱藏起來了。遠程調用是分佈式系統的基礎。編程
遠程調用通常分爲兩種,遠程過程調用(RPC)和遠程方法調用(RMI)。json
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>
響應的數據:oop
<?xml version='1.0' ?> <methodResponse> <params> <param> <value> <int> 7 </int> </value> </param> </params> </methodResponse>
RMIcode
RMI意爲遠程方法調用,粒度比RPC要大,由於它的基本單位是對象。其大體思路是這樣的:建立RMI服務器對象,將實例化的某個對象以指定的服務名稱(也能夠是多個對象,可是服務名稱不該相同)註冊到RMI服務器對象中,以後啓動RMI服務器。服務器等待客戶端發送的數據(包括服務名稱、函數名、參數),將處理結果返回給客戶端。 Pyro4是一個基於python的RMI實現,下面咱們用Pyro4建立一個RMI服務器,請看server2.py:orm
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.。