日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python使用socketServer包搭建簡(jiǎn)易服務(wù)器過(guò)程詳解

瀏覽:190日期:2022-07-21 14:50:43

官方提供了socketserver包去方便我們快速的搭建一個(gè)服務(wù)器框架。

server類(lèi)

socketserver包提供5個(gè)Server類(lèi),這些單獨(dú)使用這些Server類(lèi)都只能完成同步的操作,他是一個(gè)單線程的,不能同時(shí)處理各個(gè)客戶端的請(qǐng)求,只能按照順序依次處理。

+------------+| BaseServer |+------------+ | v+-----------+ +------------------+| TCPServer |------->| UnixStreamServer |+-----------+ +------------------+ | v+-----------+ +--------------------+| UDPServer |------->| UnixDatagramServer |+-----------+ +--------------------+

兩個(gè)Mixin類(lèi)

+--------------+ +----------------+| ForkingMixIn | | ThreadingMixIn |+--------------+ +----------------+

各自實(shí)現(xiàn)了多進(jìn)程和多線程的功能(ForkingMixIn在Windows不支持)

于是將這些同步類(lèi)和Mixin類(lèi)組合就實(shí)現(xiàn)了異步服務(wù)類(lèi)的效果。

class ThreadingUDPServer(ThreadingMixIn, UDPServer): passclass ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

class ForkingUDPServer(ForkingMixIn, UDPServer): pass class ForkingTCPServer(ForkingMixIn, TCPServer): pass

基本使用

由于server需要同時(shí)處理來(lái)自多個(gè)客戶端的請(qǐng)求,需要提供異步的支持,所以通常使用上面的異步類(lèi)創(chuàng)建服務(wù)器。在Windows系統(tǒng)中沒(méi)有提供os.fork()接口,Windows無(wú)法使用多進(jìn)程的ForkingUDPServer和ForkingTCPServer,只能使用ThreadingTCPServer或者ThreadingUDPServer;而Linux和Unix多線程和多進(jìn)程版本都可以使用。

服務(wù)器主要負(fù)責(zé)接受客戶端的連接請(qǐng)求,當(dāng)一個(gè)新的客戶端請(qǐng)求到來(lái)后,將分配一個(gè)新的線程去處理這個(gè)請(qǐng)求(異步服務(wù)器ThreadingTCPServer),而與客戶端信息的交互則交給了專(zhuān)門(mén)的請(qǐng)求處理類(lèi)(RequestHandlerClass)處理。

import socketserver# 創(chuàng)建一個(gè)基于TCP的server對(duì)象,并使用BaseRequestHandler處理客戶端發(fā)送的消息server = socketserver.ThreadingTCPServer(('127.0.0.1', 8000), BaseRequestHandler) server.serve_forever() # 啟動(dòng)服務(wù)器,

只需要上面兩行代碼就可以創(chuàng)建開(kāi)啟一個(gè)服務(wù),運(yùn)行上面代碼后常看本機(jī)8000端口,發(fā)現(xiàn)有程序正在監(jiān)聽(tīng)。

C:Usersuser>netstat -anp tcp | findstr 8000TCP 127.0.0.1:8000 0.0.0.0:0 LISTENING

ThreadingTCPServer可以對(duì)我們的請(qǐng)求進(jìn)行接受,但是并不會(huì)進(jìn)行處理請(qǐng)求,處理請(qǐng)求的類(lèi)是上面指定BaseRequestHandler類(lèi),該類(lèi)可以定義handle方法來(lái)處理接受的請(qǐng)求。

BaseRequestHandler的源碼

class BaseRequestHandler: def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server self.setup() try: self.handle() finally: self.finish() def setup(self): pass def handle(self): pass def finish(self): pass

在server = socketserver.ThreadingTCPServer(('127.0.0.1', 8000), BaseRequestHandler)中,BaseRequestHandler將作為參數(shù)綁定到服務(wù)器的實(shí)例上,服務(wù)器啟動(dòng)后,每當(dāng)有一個(gè)新的客戶端接接入服務(wù)器,將會(huì)實(shí)例化一個(gè)請(qǐng)求處理對(duì)象,并傳入三個(gè)參數(shù),request(連接客戶端的socket)、client_address(遠(yuǎn)程客戶端的地址)、server(服務(wù)器對(duì)象),執(zhí)行init方法,將這三個(gè)參數(shù)保存到對(duì)應(yīng)屬性上。這個(gè)請(qǐng)求處理對(duì)象便可以與客戶端交互了。

簡(jiǎn)單示例

import socketserverimport threading class MyRequestHandler(socketserver.BaseRequestHandler): ''' BaseRequestHandler的實(shí)例化方法中,獲得了三個(gè)屬性 self.request = request # 該線程中與客戶端交互的 socket 對(duì)象。 self.client_address # 該線程處理的客戶端地址 self.server = server # 服務(wù)器對(duì)象 ''' def handle(self): while True: msg = self.request.recv() # 接受客戶端的數(shù)據(jù) if msg == b'quit' or msg == '': # 退出break print(msg.decode()) self.request.send(msg) # 將消息發(fā)送回客戶端 def finish(self): self.request.close() # 關(guān)閉套接字if __name__ == '__main__': # 創(chuàng)建一個(gè)基于TCP的server對(duì)象,并使用BaseRequestHandler處理客戶端發(fā)送的消息 server = socketserver.ThreadingTCPServer(('127.0.0.1', 8000), MyRequestHandler) server.serve_forever() # 啟動(dòng)服務(wù)器

我們創(chuàng)建了一個(gè)ThreadingTCPServer服務(wù)器,然后在傳入的處理類(lèi)MyRequestHandler,并在handle方法中提供與客戶端消息交互的業(yè)務(wù)邏輯,此處只是將客戶端的消息返回客戶端。最后我們?cè)趂inish方法中關(guān)閉資源,finish方法使用了finally機(jī)制,保證了這些代碼一定會(huì)執(zhí)行。

上一篇使用socket實(shí)現(xiàn)了一個(gè)群聊服務(wù)器,這個(gè)里使用socketServer將更加方便的實(shí)現(xiàn)

class MyRequestHandle(BaseRequestHandler): clients = {} # 在類(lèi)屬性中記錄所有與客戶端連接socket。 lock = threading.Lock() # 互斥鎖,各個(gè)線程共用 def setup(self): # 新的用戶連接時(shí),預(yù)處理,將這個(gè)新的連接加入到clients中,考慮線程安全,需要加鎖 with self.lock: self.clients[self.client_address] = self.request def handle(self): # 處理客戶端的請(qǐng)求主邏輯 while True: data = self.request.recv(1024).strip() # 接受數(shù)據(jù) if data == b'quit' or data == b'': # 客戶端退出with self.lock: self.server.clients.pop(self.client_address) self.request.close() break print('{}-{}: {}'.format(*self.client_address, data.decode())) with self.lock:for _, c in self.server.clients.items(): # 群發(fā) c.send(data) def finish(self): with server.lock: for _, c in server.clients.items():c.close() server.server_close()def main(): server = ThreadingTCPServer(('127.0.0.1', 8000), MyRequestHandle) # 將創(chuàng)建的所有線程設(shè)置為daemon線程,這樣控臺(tái)主程序退出時(shí),這個(gè)服務(wù)器的所有線程將會(huì)被結(jié)束 server.daemon_threads = True if __name__ == '__main__': main()

上面requestHandlerclass中的handle方法和finish方式對(duì)應(yīng)了上一篇中TCP服務(wù)器的recv方法和stop方法,他們處理請(qǐng)求的邏輯是相同的。只是上面使用了socketserver的代碼變少了,處理的邏輯也變少了,TCPserver幫我們完成了大量的工作,這利于軟件的快速開(kāi)發(fā)。

內(nèi)置的兩個(gè)RequestHandlerClass

StreamHandlerRequest

StreamHandlerRequest顧名思義是一種流式的求情處理類(lèi),對(duì)應(yīng)TCP協(xié)議的面向字節(jié)流的傳輸形式。我們從源代碼分析。(去除了一些次要代碼)

class StreamRequestHandler(BaseRequestHandler): rbufsize = -1 # 讀緩存 wbufsize = 0 # 寫(xiě)緩存 timeout = None # 超時(shí)時(shí)間 # IP/TCP擁塞控制的Nagle算法算法。 disable_nagle_algorithm = False def setup(self): # 實(shí)現(xiàn)了setup, self.connection = self.request if self.timeout is not None: self.connection.settimeout(self.timeout) if self.disable_nagle_algorithm: self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)# 使用 makefile方法獲得了一個(gè)只讀文件對(duì)象 rfile self.rfile = self.connection.makefile(’rb’, self.rbufsize)# 獲得一個(gè)只寫(xiě)的文件對(duì)象 wfile if self.wbufsize == 0: self.wfile = _SocketWriter(self.connection) else: self.wfile = self.connection.makefile(’wb’, self.wbufsize) def finish(self): # 負(fù)責(zé)將這個(gè) wfile 和 rfile方法關(guān)閉。 if not self.wfile.closed: try:self.wfile.flush() except socket.error:pass self.wfile.close() self.rfile.close()

使用StreamRequestHandler方法可以將這個(gè)socket包裝成一個(gè)類(lèi)文件對(duì)象,方便我們使用一套文件對(duì)象的方法處理這個(gè)socket,它沒(méi)有實(shí)現(xiàn)handle方法,我仍然需要我們實(shí)現(xiàn)。我們可以這樣使用它

class MyHandle(StreamRequestHandler): # 如果需要使用setup和finish方法,需要調(diào)用父類(lèi)方法,否則該方法將會(huì)被覆蓋。 def setup(self): super().setup() # 添加自己的需求 def handle(self): # 這里我們可以使用wfile和rfile來(lái)處理socket消息了,例如之前使用self.request.recv()方法等同于self.rfile.read() # 而 self.wfile.write 等同于 self.request.send(),在handle方法中完成業(yè)務(wù)邏輯即可 def finish(self): super().finish()server = ThreadingTCPServer('127.0.0.1', MyHandle)server.serve_forever()

StreamRequestHandler主要定義了兩個(gè)新的 wfile對(duì)象和rfile對(duì)象,來(lái)分別對(duì)這個(gè)socket進(jìn)行讀寫(xiě)操作,當(dāng)我們業(yè)務(wù)需要時(shí),比如需要使用文件接口方法時(shí),選擇繼承于StreamRequestHandler構(gòu)建我們自己處理請(qǐng)求類(lèi)來(lái)完成業(yè)務(wù)邏輯將會(huì)更加的方便。

DatagramRequestHandler

DatagramRequestHandler字面意思是數(shù)據(jù)報(bào)請(qǐng)求處理,也就是基于UDPServer的服務(wù)器才能使用該請(qǐng)求處理類(lèi)

class DatagramRequestHandler(BaseRequestHandler): def setup(self): from io import BytesIO # udp的self.request包含兩部分(data,socket)它來(lái)自于 # data, client_addr = self.socket.recvfrom(self.max_packet_size) # return (data, self.socket), client_addr # (data, self.socket)就是這個(gè)self.request,在這里將其解構(gòu),data為recvfrom接收的數(shù)據(jù) self.packet, self.socket = self.request# 該數(shù)據(jù)包封裝為 BytesIO,同樣為一個(gè)類(lèi)文件對(duì)象。 self.rfile = BytesIO(self.packet) self.wfile = BytesIO() def finish(self): self.socket.sendto(self.wfile.getvalue(), self.client_address)

從源碼可以看出,DatagramRequestHandler將數(shù)據(jù)包封裝為一個(gè)rfile,并實(shí)例化一個(gè)ByteIO對(duì)象用于寫(xiě)入數(shù)據(jù),寫(xiě)入的數(shù)據(jù)可以通過(guò)self.socket這個(gè)套接字發(fā)送。這樣可以使用rfile和wfile這兩個(gè)類(lèi)文件對(duì)象的read或者write接口來(lái)進(jìn)行一些IO方面的操作。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品亚洲a∨一区二区三区18| 亚洲va在线| av在线资源| 免费在线亚洲欧美| 免费美女久久99| 国产 日韩 欧美 综合 一区| 在线亚洲观看| 国产亚洲欧美日韩精品一区二区三区| 国产成人免费视频网站视频社区| 久久亚洲黄色| 国产精品美女在线观看直播| 国产伦精品一区二区三区千人斩| 日韩激情av在线| 日本国产欧美| 麻豆精品99| 日韩精品专区| 99精品网站| 黄色在线观看www| 欧洲在线一区| 欧美日韩免费观看一区=区三区| 天堂网在线观看国产精品| 最新日韩av| 婷婷精品在线| 青青草伊人久久| 国产精品videosex极品| 成人午夜毛片| 不卡视频在线| 日本综合视频| 精品国产乱码久久久久久樱花 | 久久天堂av| 欧洲精品一区二区三区| 亚洲欧洲一区| 日韩av网站免费在线| 国产一区二区三区视频在线| 亚洲一级影院| 日韩有码av| 久久久久久婷| 天堂va蜜桃一区二区三区| 欧美亚洲一级| caoporn视频在线| 亚洲一区国产| 欧美成人aaa| 久久久久亚洲| 日韩亚洲精品在线观看| 久久久久久网| 激情久久婷婷| 中文字幕免费一区二区| 久久精品国产免费| 中文欧美日韩| 久久亚洲人体| 只有精品亚洲| 色在线视频观看| 亚州欧美在线| 新版的欧美在线视频| 中文字幕日韩高清在线| 国产一区二区视频在线看| 亚洲欧美日本日韩| 黄色网一区二区| 玖玖玖国产精品| 精品国产精品久久一区免费式| 激情久久婷婷| 国产精品黄网站| 亚洲少妇一区| 国产精品久久久久久久久妇女| 在线精品亚洲| 另类中文字幕国产精品| 69堂免费精品视频在线播放| 亚洲福利国产| 久久午夜影院| 色综合视频一区二区三区日韩| 色老板在线视频一区二区| 国产欧美日韩视频在线| 欧美日韩视频一区二区三区| 久久99视频| 男人的天堂亚洲一区| 久久女人天堂| 在线日韩成人| 欧美中文字幕一区二区| 久久久精品国产**网站| 亚洲人妖在线| 亚洲福利一区| 91中文字幕精品永久在线| 久久精品av麻豆的观看方式| 午夜日本精品| 水蜜桃精品av一区二区| 日本vs亚洲vs韩国一区三区二区| 日韩精品影视| 欧美交a欧美精品喷水| 一区二区国产在线观看| 日韩欧美综合| 国产精品视频一区二区三区| 蜜桃视频在线观看一区| 久久精品影视| 精品国产免费人成网站| 欧美激情日韩| 国产精品中文字幕亚洲欧美| 亚洲制服欧美另类| 欧美在线影院| 尤物tv在线精品| 韩国精品主播一区二区在线观看 | 午夜精品影院| 婷婷激情一区| 亚洲永久av| 国产一区二区三区免费在线 | 日韩av有码| 久久亚洲人体| 免费在线日韩av| 国产九九精品| 欧美日韩午夜电影网| 综合亚洲自拍| 亚洲人成在线影院| 中文字幕一区二区三区四区久久 | 亚洲精品系列| 男女激情视频一区| 国产精品美女| 亚洲女人av| 首页亚洲欧美制服丝腿| 亚洲精品1区2区| 亚洲少妇自拍| 久久亚洲视频| 亚洲一级大片| 亚洲精品美女91| 中文精品电影| 日韩美女精品| 国产欧美在线| 久久久国产精品网站| 成人免费一区| 日韩高清中文字幕一区二区| 日韩欧美中文| 欧美肉体xxxx裸体137大胆| 亚洲性视频h| 最新日韩欧美| 亚洲精品在线国产| 欧美日韩一区二区国产 | 国产亚洲欧美日韩精品一区二区三区| 日韩三级精品| 欧美有码在线| 国产精品tv| 中文字幕在线免费观看视频| 久久精品青草| 国产农村妇女精品一二区| 亚洲一二av| 91亚洲无吗| 精品欧美日韩精品| 日韩精品水蜜桃| 亚洲一区日韩| 欧美专区一区| 久久久免费人体| 久久久精品五月天| 亚洲激情黄色| 日韩精品三级| 国产精品男女| 91日韩欧美| 亚洲精品1区| 日韩高清中文字幕一区| 国产经典一区| 群体交乱之放荡娇妻一区二区| 欧美精品一线| 日本色综合中文字幕| 精品国产亚洲一区二区在线观看| 日韩欧美精品一区| 视频一区免费在线观看| 国产精品入口久久| 日本久久成人网| 亚州av日韩av| 精品视频一二| 91精品xxx在线观看| 国产视频一区欧美| 国产乱子精品一区二区在线观看| 成人国产综合| 性色一区二区| 久久99国产精品视频| 欧美91视频| 国产精品久久久久久模特 | 亚洲一区二区动漫| 国产欧美88| 99视频精品全国免费| 中文一区在线| 麻豆视频一区二区| 好吊一区二区三区| 蜜桃久久久久| 亚洲欧美网站| www.51av欧美视频| 蜜臀精品久久久久久蜜臀| 久久99高清| 蜜桃久久久久久| 在线手机中文字幕| 亚洲精品自拍| 日本精品影院| 国产午夜久久av| 99精品美女| 久久国内精品自在自线400部| jizzjizz中国精品麻豆| 最新国产精品视频| 日韩精品诱惑一区?区三区| 亚洲啊v在线免费视频| 日韩在线欧美| 久久精品72免费观看| 国产二区精品| 精品一区二区男人吃奶 |