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

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

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

瀏覽:113日期:2022-07-24 15:14:47

1、背景

最近有個(gè)項(xiàng)目,需要搭建一個(gè)socket服務(wù)器,一個(gè)web服務(wù)器,然后實(shí)現(xiàn)兩個(gè)服務(wù)器之間的通訊交互。剛開(kāi)始的方案是用Python中socket模塊實(shí)現(xiàn)一個(gè)多線程的socket服務(wù)器,然后用Flask實(shí)現(xiàn)一個(gè)web服務(wù)器,他們之前通過(guò)線程交互實(shí)現(xiàn)通訊。但是在我看來(lái)這個(gè)方案有例外一個(gè)更好的解決方法,就是用Torndao框架。鑒于網(wǎng)上用Tornado實(shí)現(xiàn)一個(gè)程序同時(shí)實(shí)現(xiàn)web服務(wù)和socket服務(wù)器并且實(shí)現(xiàn)交互的文章幾乎沒(méi)有,所以記錄一下。覺(jué)得寫(xiě)得好麻煩點(diǎn)個(gè)贊,寫(xiě)得不好請(qǐng)指出,有疑問(wèn)可以留言。

2、準(zhǔn)備

2.1、環(huán)境部署

Python3.x pip3 install Tornado

2.2、目錄結(jié)構(gòu)

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

目錄結(jié)構(gòu)如上圖,這個(gè)目錄結(jié)構(gòu)包括文件命名只是我的個(gè)人習(xí)慣。其實(shí)目錄結(jié)構(gòu)不固定,只要合理就行。另外,原本項(xiàng)目是前后分離的只需要實(shí)現(xiàn)API接口,所以我這里就沒(méi)有涉及到HTML的東西。

3、服務(wù)器的實(shí)現(xiàn)

3.1、Socket服務(wù)器實(shí)現(xiàn)

socket服務(wù)器部分實(shí)現(xiàn)主要靠 Tornado中的TCPServer類(lèi)

3.1.1、 導(dǎo)入類(lèi)

socket_server.py:

from tornado.iostream import IOStream # 這句可以沒(méi)有,只是作為參數(shù)的代碼提示from tornado.tcpserver import TCPServer

3.1.2、 構(gòu)建一個(gè)Connecter類(lèi)

socket_server.py:

class Connecter: clients = set() # 存放連接的客戶(hù)端 async def init(self, stream: IOStream, address: tuple): ''' 注意這個(gè)不是構(gòu)造方法,這里不用構(gòu)造方法是為了方便后續(xù)的與web端相互通信 ''' self.stream, self.address = stream, address self.clients.add(self) print('{address} 上線!'.format(address=address)) self.stream.set_close_callback(self.onClose) # 客戶(hù)端離線的時(shí)候會(huì)被調(diào)用 await self.receive() # 接受消息 async def receive(self): ''' 接受消息 ''' while True: try: # 因?yàn)楫惒降脑颉?赡茉O(shè)備離線后還在接收消息,所以try一下,不讓錯(cuò)誤打印出來(lái),其實(shí)打印了錯(cuò)誤也不影響程序運(yùn)行data = await self.stream.read_bytes(num_bytes=1024, partial=True) # num_bytes:每次最多接收字節(jié),partial:數(shù)據(jù)中斷后視為接收完成print(data)# TODO:接收到數(shù)據(jù)的處理 except: pass def send(self, data): ''' 發(fā)送消息 :param data: 消息內(nèi)容 ''' self.stream.write(bytes(data.encode(’utf8’))) def onClose(self): ''' 客戶(hù)端離線 ''' print('{address} 離線!'.format(address=self.address)) self.clients.remove(self) # 在clients內(nèi)刪掉該客戶(hù)端

3.1.3、 構(gòu)建一個(gè)SocketServer類(lèi)

socket_server.py:

class SocketServer(TCPServer): # 需要繼承TCPServer這個(gè)類(lèi) async def handle_stream(self, stream: IOStream, address: tuple): # 實(shí)現(xiàn)類(lèi)里面的handle_stream方法 await Connecter().init(stream, address) # 每次有客戶(hù)端連入都實(shí)例化一個(gè)Connecter類(lèi)

3.2、Web服務(wù)器實(shí)現(xiàn)

3.2.1、 實(shí)現(xiàn)一個(gè)requestHandler

web_test.py:

from tornado.web import RequestHandler # 導(dǎo)入RequestHandler類(lèi)class TestApiHandler(RequestHandler): # 繼承RequestHandler類(lèi) def get(self): # 實(shí)現(xiàn)GET方法,GET請(qǐng)求會(huì)執(zhí)行這個(gè)方法 pass def post(self): # 實(shí)現(xiàn)POST方法,POST請(qǐng)求會(huì)執(zhí)行這個(gè)方法 pass

3.2.2、 實(shí)現(xiàn)web app

web_server.py:

from tornado.web import Application # 導(dǎo)入Tornado的Application類(lèi)from .src.web_test import TestApiHandler # 導(dǎo)入我們自己寫(xiě)的TestApiHandler類(lèi)def webServerApp(): # 構(gòu)造出webApp return Application([ (r’/api_test/’, TestApiHandler), # 把/api_test/路由到TestApiHandler ])

3.3、程序入口

3.3.1、 導(dǎo)入web_server和socket_server,還有導(dǎo)入tornado的ioloop

main.py:

from web_server.web_server import webServerAppfrom socket_server.socket_server import SocketServerfrom tornado import ioloopfrom tornado.options import define, options

3.3.2、 定義默認(rèn)端口

main.py

#這里用define定義端口,可以方便使用命令行參數(shù)的形式修改端口define('socketPort', 8888, type=int) # socket默認(rèn)使用8888端口define('webPort', 8080, type=int) # web默認(rèn)使用8080端口

3.3.3、 啟動(dòng)代碼

main.py

def main(): socket_server = SocketServer() socket_server.listen(options.socketPort, ’0.0.0.0’) print('socket服務(wù)器啟動(dòng),端口:{port}'.format(port=options.socketPort)) app = webServerApp() app.listen(options.webPort, ’0.0.0.0’) print('web服務(wù)器啟動(dòng),端口:{port}'.format(port=options.webPort)) ioloop.IOLoop.current().start()if __name__ == ’__main__’: main()

4、服務(wù)器運(yùn)行效果

到此,一個(gè)混合型的socket+web服務(wù)器已經(jīng)搭建好了。我們我們運(yùn)行main.py文件可以看到打印的信息,socket和web都正常運(yùn)行。

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

我在這里簡(jiǎn)單地寫(xiě)了一個(gè)socket客戶(hù)端測(cè)試,代碼如下:

import socketimport datetimeclass Client: def __init__(self): with socket.create_connection(('127.0.0.1', 8888)) as sock: while True:msg = sock.recv(1024)if len(msg) > 0: print(msg) sock.send(bytes(str(datetime.datetime.now).encode(’utf8’)))msg = [] if __name__ == '__main__': Client()

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

可以看到tornado異步的形式實(shí)現(xiàn)了多客戶(hù)端同時(shí)接入socket。同時(shí)也可以測(cè)試web接口是正常的,如下圖:

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

5、Web服務(wù)器與Socket服務(wù)器交互

重點(diǎn)來(lái)了,web和socket怎樣實(shí)現(xiàn)交互呢?其實(shí)很簡(jiǎn)單。

5.2、 web >> socket

web_test.py -> TestApiHandler -> post:

5.2.1、 導(dǎo)入Connecter類(lèi)

from socket_server.socket_server import Connecter

5.2.2、 實(shí)現(xiàn)請(qǐng)求接口發(fā)送消息到socket客戶(hù)端

def post(self): # 實(shí)現(xiàn)POST方法,POST請(qǐng)求會(huì)執(zhí)行這個(gè)方法 msg = self.get_argument('msg') # 得到post請(qǐng)求中的msg的值 ip = self.get_argument(’ip’) # 得到要發(fā)送的ip c = Connecter() # 實(shí)例化Connecter類(lèi) counter = 0 # 記錄發(fā)送到客戶(hù)端的個(gè)數(shù) for client in c.clients: # type:Connecter if client.address[0] == ip: # 根據(jù)ip發(fā)送client.send(msg) # 發(fā)送消息counter += 1 # 計(jì)數(shù)加1 self.write('{’send_counter’:' + str(counter) + '}')

5.2.3、 效果

請(qǐng)求接口可以返回?cái)?shù)據(jù),已經(jīng)成功發(fā)送一個(gè)客戶(hù)端

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

客戶(hù)端也能收到消息:

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

5.1、 socket >> web

其實(shí)socket發(fā)送的消息讓web馬上收到消息是不太現(xiàn)實(shí)的,但是我們可以把數(shù)據(jù)保存起來(lái)(可以是數(shù)據(jù)庫(kù)、全局變量、緩存……),然后通過(guò)api接口再把數(shù)據(jù)取出。另外還有一種方法是通過(guò)socket和websocket進(jìn)行交互通訊,這種方法是推薦的方法,同樣的也可以用Tornado去實(shí)現(xiàn),感興趣可以去研究一下也很簡(jiǎn)單。如何有需要我提供socket、websocket、web三個(gè)端都互相交互的例子可以留言。這里為了簡(jiǎn)單一點(diǎn),我使用一個(gè)類(lèi)作為全局變量來(lái)保存數(shù)據(jù),然后用接口訪問(wèn),拿出這個(gè)類(lèi)的值來(lái)演示一下效果。

5.1.1、 聲明類(lèi)作為全局變量

socket_data_processing.py

class SocketData: msg = ''

5.1.2、 接受到的消息保存到這個(gè)類(lèi)里面的msg

socket_server.py -> Connecter -> receive

async def receive(self): ''' 接受消息 ''' while True: try: # 因?yàn)楫惒降脑颉?赡茉O(shè)備離線后還在接收消息,所以try一下,不讓錯(cuò)誤打印出來(lái),其實(shí)打印了錯(cuò)誤也不影響程序運(yùn)行data = await self.stream.read_bytes(num_bytes=1024, partial=True) # num_bytes:每次最多接收字節(jié),partial:數(shù)據(jù)中斷后視為接收完成print(data)from .src.socket_data_processing import SocketDataSocketData.msg = data.decode(’utf8’) except:pass

5.1.3、 用get方法顯示socket顯示回來(lái)的數(shù)據(jù)

web_test.py -> TestApiHandler -> get:

def get(self): # 實(shí)現(xiàn)GET方法,GET請(qǐng)求會(huì)執(zhí)行這個(gè)方法 from socket_server.src.socket_data_processing import SocketData self.write(SocketData.msg)

5.1.4、 效果

Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法

可以看到,從socket傳過(guò)來(lái)的字符串,被我通過(guò)Api讀取到了。

6、完整代碼GitHub:https://github.com/JohnDoe1996/socket-web

到此這篇關(guān)于Python Tornado實(shí)現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實(shí)現(xiàn)交互的方法的文章就介紹到這了,更多相關(guān)Python WEB服務(wù)器Socket服務(wù)器共存交互內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩精品视频网| 日韩动漫一区| 欧美激情福利| www.51av欧美视频 | 在线成人直播| 亚洲色诱最新| 日本成人在线不卡视频| 免费在线日韩av| 久久久久久一区二区| 欧美成人综合| 亚洲一区二区三区高清| 日韩av电影一区| 精品视频在线你懂得| 久久99精品久久久野外观看| 国产h片在线观看| 99亚洲视频| 久久精品一本| 亚洲一区二区三区中文字幕在线观看| 国产精品视频首页| 欧美日韩国产一区二区三区不卡 | 久久伊人久久| 夜夜精品视频| 98精品视频| 亚洲综合精品| 国产一区二区三区四区二区| 国产视频一区免费看| 精品久久国产一区| 亚洲精品日韩久久| 欧美~级网站不卡| 激情欧美亚洲| 精品黄色一级片| 日韩欧美高清一区二区三区| 99国产精品免费视频观看| 国产精品尤物| 日本中文字幕一区二区视频| 国产毛片久久久| 国产农村妇女精品一二区| 成人亚洲一区二区| 99热精品在线| 亚洲先锋成人| 秋霞国产精品| 成人午夜网址| 国产精品视频一区二区三区 | 欧美一级久久| 在线精品福利| 91久久中文| 亚洲特色特黄| 国产精品7m凸凹视频分类| 日韩国产欧美| 捆绑调教美女网站视频一区| 国产欧美日韩一区二区三区在线| 视频一区中文字幕精品 | 精品网站aaa| 四季av一区二区凹凸精品| 国产精品99久久免费| 国产精品视频一区二区三区四蜜臂 | 精品视频一区二区三区在线观看| 国产精品日韩精品中文字幕| 国产精品久久久亚洲一区| 欧美视频一区| 91偷拍一区二区三区精品| 国产精品久久久久久久免费观看| 国产一区二区三区天码| 亚洲深夜视频| 亚洲天堂成人| 亚洲不卡视频| 国产精品99精品一区二区三区∴ | 99在线精品免费视频九九视| 老司机精品久久| 国产日韩欧美高清免费| 精品国产麻豆| 婷婷综合五月| 日韩精品社区| 91中文字幕精品永久在线| 欧美日韩国产一区二区三区不卡| 综合精品一区| 日韩成人精品一区| 免费日韩视频| 久久中文精品| 亚洲资源av| 国产不卡精品| 亚洲深夜福利在线观看| 日精品一区二区三区| 97精品国产| 91大神在线观看线路一区| 日本а中文在线天堂| 亚洲天堂免费| 激情欧美一区二区三区| 国产美女精品视频免费播放软件| 久久久久美女| 美女久久精品| 日本一区二区三区视频在线看| 久久香蕉网站| 日本欧美韩国一区三区| 亚洲精品a级片| 中文字幕在线视频网站| 91亚洲精品在看在线观看高清| 日韩成人精品一区二区| 日本强好片久久久久久aaa| 亚洲一区日本| 色婷婷精品视频| 成人在线免费观看网站| 国产精品一区二区三区av| 亚洲欧美视频| 婷婷亚洲五月| 99久久久久久中文字幕一区| 精品中国亚洲| 欧美a级一区二区| 国产精品久久久免费| 欧美日韩一区二区国产| 亚洲精品系列| 日韩精品一区二区三区免费视频| 狠狠操综合网| 日韩午夜精品| 日韩精品一二区| 日av在线不卡| 亚州国产精品| 欧美日韩伊人| 麻豆视频久久| 日韩不卡在线| 欧美午夜精品一区二区三区电影| 在线一区视频观看| 韩国一区二区三区视频| 国产美女视频一区二区| 国产精品扒开腿做爽爽爽软件| 欧美在线不卡| 精品国产欧美日韩一区二区三区| 国产日韩精品视频一区二区三区| 久久国内精品视频| 精品久久久久中文字幕小说| 国产va在线视频| 久久蜜桃精品| 综合激情一区| 国产欧美大片| 国产精品字幕| 最新国产精品视频| 国产精品亚洲人成在99www| 国内精品麻豆美女在线播放视频| 樱桃视频成人在线观看| 99国产精品久久久久久久| 日本少妇精品亚洲第一区| 精品国产欧美| 香蕉精品视频在线观看| 在线看片日韩| 不卡专区在线| 日韩欧美中文字幕一区二区三区| 欧美影院精品| 午夜国产一区二区| 日本va欧美va瓶| 婷婷精品视频| 日韩精品福利一区二区三区| 国产一区二区三区亚洲| 日本亚洲欧美天堂免费| 精品三级久久| 久久不见久久见免费视频7| 国产一区亚洲| 美日韩一区二区三区| 欧美成人精品| 国产在线一区不卡| 婷婷综合成人| 亚洲国产综合在线看不卡| 国产精品对白| 中文字幕免费一区二区| 韩国三级一区| 国产精品久久久久毛片大屁完整版| 欧美亚洲国产日韩| 蜜臀久久99精品久久一区二区| 国产精品嫩模av在线| 91久久午夜| 91精品啪在线观看国产18| 国产精品久久久久久久久免费高清| 中国女人久久久| 日产精品一区二区| 亚洲一二三区视频| 欧美日韩国产免费观看视频| 给我免费播放日韩视频| 国产精品玖玖玖在线资源| 日韩毛片网站| 亚洲欧洲国产精品一区| 美女国产精品| 麻豆精品网站| 亚洲欧美日韩国产一区| 黄色日韩在线| 一区三区视频| 美女久久一区| 亚洲专区视频| 日韩av在线免费观看不卡| 亚洲四虎影院| 91免费精品| 91精品在线观看国产| 99久久亚洲精品蜜臀| 欧美精品羞羞答答| 国产精品美女久久久| 亚洲视频www| 日韩高清二区| 精品美女在线视频| 欧美午夜精彩| 亚洲精一区二区三区| 青青草91视频| 岛国av在线播放|