Python網(wǎng)絡編程之xmlrpc模塊
簡介
rpc:遠程過程調(diào)用協(xié)議。簡單的來說就是客戶端可以很方便得遠程調(diào)用服務端的接口程序,而不用管底層是如何實現(xiàn)的。
XML-RPC的全稱是XML Remote Procedure Call,即XML(標準通用標記語言下的一個子集)遠程過程調(diào)用。它是一套允許運行在不同操作系統(tǒng)、不同環(huán)境的程序?qū)崿F(xiàn)基于Internet過程調(diào)用的規(guī)范和一系列的實現(xiàn)。這種遠程過程調(diào)用使用http作為傳輸協(xié)議,XML作為傳送信息的編碼格式。Xml-Rpc的定義盡可能的保持了簡單,但同時能夠傳送、處理、返回復雜的數(shù)據(jù)結(jié)構(gòu)。這個過程也被大家稱為“分布式計算”。
xmlrpc:使用http協(xié)議作為傳輸協(xié)議的rpc機制。
1、注冊函數(shù):register_function
以下是定義了一個函數(shù)的xmlrpc服務端。
register_function用于注冊一個供調(diào)用的函數(shù),第一個參數(shù)為自己實現(xiàn)的方法名,第二個參數(shù)為供客戶端調(diào)用的方法名。
from xmlrpc.server import SimpleXMLRPCServer #導入模塊 s = SimpleXMLRPCServer(("10.55.22.11",4242)) #服務端ip假設為10.55.22.11,端口假設為4242 def twice(x): #定義函數(shù) return x*2 s.register_function(twice) #注冊函數(shù)(讓客戶端發(fā)現(xiàn)) s.serve_forever() #啟動服務端
下面是該服務端對應的xmlrpc客戶端
根據(jù)url和端口號初始化一個服務器對象,然后調(diào)用需要的方法即可:
import xmlrpc.client #導入模塊 s = xmlrpc.client.ServerProxy('http://10.55.22.11:4242') #鏈接服務端 print(s.twice(2)) #調(diào)用函數(shù)
調(diào)用成功成功后服務端會顯示
2、注冊類方法函數(shù):register_instance
服務端如:
from xmlrpc.server import SimpleXMLRPCServer # 導入模塊 s = SimpleXMLRPCServer(("10.81.10.57",4242)) # 設置服務端ip和端口 class Animal: #定義類 def rabit(self, amount): return 4*amount def chicken(self, amount): return 2*amount s.register_instance(Animal()) # 注冊類方法函數(shù)(讓客戶端發(fā)現(xiàn)) s.serve_forever() # 啟動服務端
對應的客戶端如下:
import xmlrpc.client # 導入模塊 s = xmlrpc.client.ServerProxy('http://10.81.10.57:4242') # 鏈接服務端 print(s.rabit(2)) # 調(diào)用函數(shù) print(s.chicken(2))
3、dispatch方法
接下來要修改一些注冊類方法函數(shù)接口的參數(shù),對應的修改一下類定義。通過在類定義中添加—_dispatch方法可以在遠程調(diào)用接口的時候經(jīng)過_dispach。
服務端如下:
from xmlrpc.server import SimpleXMLRPCServer # 導入模塊 s = SimpleXMLRPCServer(("10.81.10.57",4242)) # 設置服務端ip和端口 class Animal: # 定義類 def _dispatch(self, method, param): # 定義_dispatch方法 print(method) # 在服務端顯示調(diào)用的方法名 func = getattr(self, method) # 調(diào)用接口 return func(*param) def rabit(self, amount): return 4*amount def chicken(self, amount): return 2*amount s.register_instance(Animal()) # 注冊函數(shù)(讓客戶端發(fā)現(xiàn)) s.serve_forever() # 啟動服務端
客戶端如下:
import xmlrpc.client # 導入模塊 s = xmlrpc.client.ServerProxy('http://10.81.10.57:4242') # 鏈接服務端 print(s.rabit(2)) # 調(diào)用函數(shù) print(s.chicken(2))
注: 服務器端運行結(jié)果:
4、多線程訪問
初始化服務器用的不再是SimpleXMLRPCServer了,而是自定義的一個類,繼承自兩個基類,ThreadingMixIn使其能夠支持多線程,其余的操作方式還是和普通的一樣。
并且我們新增了一個函數(shù),接受兩個參數(shù),計算和,可以看到無論參數(shù)數(shù)量多少,我們注冊函數(shù)的時候都只寫函數(shù)名。
from xmlrpc.server import SimpleXMLRPCServer from socketserver import ThreadingMixIn class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): pass # 調(diào)用函數(shù)1 def respon_string(str): return "get string:%s"%str # 調(diào)用函數(shù)2 def add(x, y): return x + y if __name__ == '__main__': server = ThreadXMLRPCServer(('localhost', 8888)) # 初始化 server.register_function(respon_string, "get_string") # 注冊函數(shù)1 server.register_function(add, 'add') # 注冊函數(shù)2 print ("Listening for Client") server.serve_forever() # 保持等待調(diào)用狀態(tài)
客戶端代碼如下:
from xmlrpc.client import ServerProxy if __name__ == '__main__': server = ServerProxy("http://localhost:8888") # 初始化服務器 print (server.get_string("cloudox")) # 調(diào)用函數(shù)1并傳參 print (server.add(8, 8)) # 調(diào)用函數(shù)2并傳參
5、文件上傳&下載
RPC除了傳參以外還可以在客戶端與服務器之間傳輸文件——客戶端既可以從服務器下載文件,也可以上傳文件到服務器。
傳輸文件要用到xmlrpc.client.Binary這個庫,如果要實現(xiàn)從服務器下載文件的功能,那么服務器端也需要導入這個庫,即使它名義上屬于client庫。
傳輸文件的基本步驟是:
- 用open打開一個文件(沒有的話會創(chuàng)建),確定是讀權(quán)限還是寫權(quán)限;
- 在文件發(fā)送端通過調(diào)用xmlrpc.client.Binary來進行文件的傳輸,接收端通過值.data來獲取內(nèi)容(詳見代碼);
- 關(guān)閉文件。
服務器:
初始化服務器時多了個參數(shù)allow_none=True,這是允許不返回參數(shù)給客戶端,因為文件上傳的函數(shù)都是沒有返回值的,不設置這個參數(shù)會報錯,實際上這里也應該返回一個值告訴客戶端是否上傳成功。
文件上傳的代碼中可以看到,寫入的是data.data,單單data是會報錯的,因為實際上要寫入的是Binary.data,這在下面的客戶端代碼下載文件時也會看到。
from xmlrpc.server import SimpleXMLRPCServer from socketserver import ThreadingMixIn import xmlrpc.client class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer): pass # 供客戶端下載文件 def image_get(): handle = open("boy.jpg", 'rb') return xmlrpc.client.Binary(handle.read()) # 供客戶端上傳文件 def image_put(data): handle = open("get_girl.jpg", 'wb') handle.write(data.data) handle.close() if __name__ == '__main__': server = ThreadXMLRPCServer(('localhost', 8888), allow_none=True) # 初始化 server.register_function(image_put, 'image_put') server.register_function(image_get, 'image_get') print ("Listening for Client") server.serve_forever() # 保持等待調(diào)用狀態(tài)
客戶端:
可以看到,下載文件時寫入的也是獲取到的返回值.data,而不是返回值本身,這個一定要注意。
from xmlrpc.client import ServerProxy import xmlrpc.client if __name__ == '__main__': server = ServerProxy("http://localhost:8888", allow_none=True) # 上傳文件 put_handle = open("girl.jpg", 'rb') server.image_put(xmlrpc.client.Binary(put_handle.read())) put_handle.close() # 下載文件 get_handle = open("get_boy.jpg", 'wb') get_handle.write(server.image_get().data) get_handle.close()
到此這篇關(guān)于Python網(wǎng)絡編程之xmlrpc模塊的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Pytorch實現(xiàn)將label變成one hot編碼的兩種方式
這篇文章主要介紹了Pytorch實現(xiàn)將label變成one hot編碼的兩種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02python生成tensorflow輸入輸出的圖像格式的方法
本篇文章主要介紹了python生成tensorflow輸入輸出的圖像格式的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02TensorFlow繪制loss/accuracy曲線的實例
今天小編就為大家分享一篇TensorFlow繪制loss/accuracy曲線的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01解決pyCharm中 module 調(diào)用失敗的問題
今天小編就為大家分享一篇解決pyCharm中 module 調(diào)用失敗的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02Python中函數(shù)的參數(shù)定義和可變參數(shù)用法實例分析
這篇文章主要介紹了Python中函數(shù)的參數(shù)定義和可變參數(shù)用法,以實例形式較為詳細的分析了Python中參數(shù)定義與可變參數(shù)的具體使用方法,需要的朋友可以參考下2015-06-06