最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2020年05月26日 10:02:50   作者:John_Doe.  
這篇文章主要介紹了Python Tornado實現(xiàn)WEB服務(wù)器Socket服務(wù)器共存并實現(xiàn)交互的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1、背景

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

2、準(zhǔn)備

2.1、環(huán)境部署

  • Python3.x
  • pip3 install Tornado

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


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

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

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

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

3.1.1、 導(dǎo)入類

socket_server.py:

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

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

socket_server.py:

class Connecter:

  clients = set()   # 存放連接的客戶端

  async def init(self, stream: IOStream, address: tuple):
    """
    注意這個不是構(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) # 客戶端離線的時候會被調(diào)用
    await self.receive()    # 接受消息

  async def receive(self):
    """
    接受消息
    """
    while True:
      try:  # 因為異步的原因??赡茉O(shè)備離線后還在接收消息,所以try一下,不讓錯誤打印出來,其實打印了錯誤也不影響程序運行
        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):
    """
    客戶端離線
    """
    print("{address} 離線!".format(address=self.address))
    self.clients.remove(self) # 在clients內(nèi)刪掉該客戶端

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

socket_server.py:

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

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

3.2.1、 實現(xiàn)一個requestHandler

web_test.py:

from tornado.web import RequestHandler   # 導(dǎo)入RequestHandler類


class TestApiHandler(RequestHandler):    # 繼承RequestHandler類

  def get(self):   # 實現(xiàn)GET方法,GET請求會執(zhí)行這個方法
    pass

  def post(self):   # 實現(xiàn)POST方法,POST請求會執(zhí)行這個方法
    pass

3.2.2、 實現(xiàn)web app

web_server.py:

from tornado.web import Application     # 導(dǎo)入Tornado的Application類
from .src.web_test import TestApiHandler  # 導(dǎo)入我們自己寫的TestApiHandler類


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 webServerApp
from socket_server.socket_server import SocketServer
from tornado import ioloop
from 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、 啟動代碼

main.py

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


if __name__ == '__main__':
  main()

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

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


我在這里簡單地寫了一個socket客戶端測試,代碼如下:

import socket
import datetime


class 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()


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

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

重點來了,web和socket怎樣實現(xiàn)交互呢?其實很簡單。

5.2、 web >> socket

web_test.py -> TestApiHandler -> post:

5.2.1、 導(dǎo)入Connecter類

from socket_server.socket_server import Connecter

5.2.2、 實現(xiàn)請求接口發(fā)送消息到socket客戶端

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

5.2.3、 效果

請求接口可以返回數(shù)據(jù),已經(jīng)成功發(fā)送一個客戶端


客戶端也能收到消息:

5.1、 socket >> web

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

5.1.1、 聲明類作為全局變量

socket_data_processing.py

class SocketData:
  msg = ""

5.1.2、 接受到的消息保存到這個類里面的msg

socket_server.py -> Connecter -> receive

 async def receive(self):
    """
    接受消息
    """
    while True:
      try:  # 因為異步的原因??赡茉O(shè)備離線后還在接收消息,所以try一下,不讓錯誤打印出來,其實打印了錯誤也不影響程序運行
        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 SocketData
        SocketData.msg = data.decode('utf8')
      except:
        pass

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

web_test.py -> TestApiHandler -> get:

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

5.1.4、 效果


可以看到,從socket傳過來的字符串,被我通過Api讀取到了。

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

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

相關(guān)文章

  • Python+PyQt5實現(xiàn)多屏幕協(xié)同播放功能

    Python+PyQt5實現(xiàn)多屏幕協(xié)同播放功能

    在現(xiàn)代會議展示、數(shù)字廣告、展覽展示等場景中,多屏幕協(xié)同播放已成為剛需,下面我們就來看看如何利用Python和PyQt5開發(fā)一套功能強(qiáng)大的跨屏播控系統(tǒng)吧
    2025-03-03
  • 深入了解Python中計數(shù)器Counter的使用

    深入了解Python中計數(shù)器Counter的使用

    計數(shù)器counter是包含在collections模塊中的容器,這篇文章主要來和大家聊聊計數(shù)器counter的使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Python使用gluon/mxnet模塊實現(xiàn)的mnist手寫數(shù)字識別功能完整示例

    Python使用gluon/mxnet模塊實現(xiàn)的mnist手寫數(shù)字識別功能完整示例

    這篇文章主要介紹了Python使用gluon/mxnet模塊實現(xiàn)的mnist手寫數(shù)字識別功能,結(jié)合完整實例形式分析了Python調(diào)用gluon/mxnet模塊識別手寫字的具體實現(xiàn)技巧,需要的朋友可以參考下
    2019-12-12
  • Python中XML轉(zhuǎn)JSON、XML轉(zhuǎn)字典代碼示例

    Python中XML轉(zhuǎn)JSON、XML轉(zhuǎn)字典代碼示例

    大家都知道python的字典和json類似,那么可不可以先將xml轉(zhuǎn)換成json再去做其他的事情呢,下面這篇文章主要給大家介紹了關(guān)于Python中XML轉(zhuǎn)JSON、XML轉(zhuǎn)字典的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • python內(nèi)建類型與標(biāo)準(zhǔn)類型

    python內(nèi)建類型與標(biāo)準(zhǔn)類型

    這篇文章主要介紹了python內(nèi)建類型與標(biāo)準(zhǔn)類型,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Python 有可能刪除 GIL 嗎?

    Python 有可能刪除 GIL 嗎?

    這篇文章主要介紹了Python 有可能刪除 GIL 嗎,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • 詳解PyQt5信號與槽的幾種高級玩法

    詳解PyQt5信號與槽的幾種高級玩法

    這篇文章主要介紹了詳解PyQt5信號與槽的幾種高級玩法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Python類方法@classmethod()的具體使用

    Python類方法@classmethod()的具體使用

    @classmethod 是一個函數(shù)修飾符,它表示接下來的是一個類方法,而對于平常我們見到的則叫做實例方法,本文主要介紹了Python類方法@classmethod()的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Python使用Matplotlib實現(xiàn)Logos設(shè)計代碼

    Python使用Matplotlib實現(xiàn)Logos設(shè)計代碼

    這篇文章主要介紹了Python使用Matplotlib實現(xiàn)Logos設(shè)計代碼,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Python實現(xiàn)字典的key和values的交換

    Python實現(xiàn)字典的key和values的交換

    本文給大家分別介紹了在python3.0和2.7版本下實現(xiàn)字典的key和values的交換的程序代碼,非常的簡單實用,有需要的小伙伴可以參考下。
    2015-08-08

最新評論

尚志市| 苏尼特左旗| 临湘市| 沁源县| 板桥市| 九寨沟县| 平果县| 镇平县| 茂名市| 简阳市| 永宁县| 赤城县| 堆龙德庆县| 织金县| 庆阳市| 湖北省| 鹿泉市| 鸡泽县| 牟定县| 修水县| 九龙城区| 遂平县| 革吉县| 托克托县| 古浪县| 泊头市| 清河县| 楚雄市| 启东市| 五常市| 双鸭山市| 漳平市| 抚宁县| 赞皇县| 花垣县| 巨鹿县| 西青区| 策勒县| 梅州市| 离岛区| 体育|