简体   繁体   English

客户端连接后通过ws从其他类发送数据

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

I want to send data through websockets as soon as a client is connected. 我想在客户端连接后立即通过websocket发送数据。 The Data is at an other place then the Websocket Handler. 数据位于Websocket处理程序之后的另一个位置。 How can i get the data to the client ? 我如何将数据发送给客户端?

The server should hold the loop and the Handler. 服务器应保留循环和处理程序。 In the connector i connect to a tcp socket to get the data out of some hardware. 在连接器中,我连接到tcp套接字以从某些硬件中获取数据。 I expect to have not more then 6 Websockets open once a time. 我希望一次打开6个Websocket。 The Data comes as a stream out of the TCP socket. 数据作为流从TCP套接字流出。

server.py 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 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)

You can use Tornado's add_callback function to call a method on your websocket handler to send the messages. 您可以使用Tornado的add_callback函数在websocket处理程序上调用方法来发送消息。

Here's an example: 这是一个例子:

1. Create an additional method on your websocket handler which will receive a message from connector.py and will send to connected clients: 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. Pass the currently running IOLoop and WSHandler.send_data to your connector.py : 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. Then modify main_task function in connector.py to receive io_loop and callback . 3.然后在connector.py修改main_task函数,以接收io_loopcallback Then pass io_loop and callback to RAMReceiver . 然后将io_loop callbackRAMReceiver并进行callback

4. Finally, use io_loop.add_callback to call WSHandler.send_data : 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