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