簡體   English   中英

客戶端連接后通過ws從其他類發送數據

[英]Send data from an other class through ws after client connected

我想在客戶端連接后立即通過websocket發送數據。 數據位於Websocket處理程序之后的另一個位置。 我如何將數據發送給客戶端?

服務器應保留循環和處理程序。 在連接器中,我連接到tcp套接字以從某些硬件中獲取數據。 我希望一次打開6個Websocket。 數據作為流從TCP套接字流出。

server.py

import os
from tornado import web, websocket
import asyncio
import connector


class StaticFileHandler(web.RequestHandler):

    def set_default_headers(self):
        self.set_header("Access-Control-Allow-Origin", "*")

    def get(self):
        self.render('index.html')


class WSHandler(websocket.WebSocketHandler):
    def open(self):
        print('new connection')
        self.write_message("connected")

    def on_message(self, message):
        print('message received %s' % message)
        self.write_message("pong")

    def on_close(self):
        print('connection closed')


public_root = 'web_src'

handlers = [
    (r'/', StaticFileHandler),
    (r'/ws', WSHandler),
]

settings = dict(
    template_path = os.path.join(os.path.dirname(__file__), public_root),
    static_path = os.path.join(os.path.dirname(__file__), public_root),
    debug = True
)

app = web.Application(handlers, **settings)

sensorIP = "xxx.xxx.xxx.xxx"

if __name__ == "__main__":
    app.listen(8888)
    asyncio.ensure_future(connector.main_task(sensorIP))
    asyncio.get_event_loop().run_forever()

connector.py

import yaml
import asyncio


class RAMReceiver:
    def __init__(self, reader):
        self.reader = reader
        self.remote_data = None
        self.initParams = None

    async def work(self):
        i = 0
        while True:
            data = await self.reader.readuntil(b"\0")
            self.remote_data = yaml.load(data[:-1].decode("utf-8", 
            "backslashreplace"))

            # here i want to emit some data
            # send self.remote_data to websockets 

            if i == 0:
                i += 1
                self.initParams = self.remote_data

                # here i want to emit some data after open event is 
                # triggered
                # send self.initParams as soon as a client has connected


async def main_task(host):
    tasks = []
    (ram_reader,) = await asyncio.gather(asyncio.open_connection(host, 
    51000))
    receiver = RAMReceiver(ram_reader[0])
    tasks.append(receiver.work())

while True:
    await asyncio.gather(*tasks)

您可以使用Tornado的add_callback函數在websocket處理程序上調用方法來發送消息。

這是一個例子:

1.在您的websocket處理程序上創建一個其他方法,該方法將接收來自connector.py的消息並將其發送給已連接的客戶端:

# server.py

class WSHandler(websocket.WebSocketHandler):

    # make it a classmethod so that 
    # it can be accessed directly
    # from class without `self`
    @classmethod 
    async def send_data(cls, data):
         # write your code for sending data to client

2.將當前正在運行的IOLoopWSHandler.send_dataconnector.py

# server.py

from tornado import ioloop

...

if __name__ == "__main__":
    ...
    io_loop = ioloop.IOLoop.current() # current IOLoop
    callback = WSHandler.send_data
    # pass io_loop and callback to main_task
    asyncio.ensure_future(connector.main_task(sensorIP, io_loop, callback))
    ...

3.然后在connector.py修改main_task函數,以接收io_loopcallback 然后將io_loop callbackRAMReceiver並進行callback

4.最后,使用io_loop.add_callback調用WSHandler.send_data

class RAMReceiver:
    def __init__(self, reader, io_loop, callback):
        ...
        self.io_loop = io_loop
        self.callback = callback

    async def work(self):
        ...
        data = "Some data"
        self.io_loop.add_callback(self.callback, data)
        ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM