[英]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.将当前正在运行的
IOLoop
和WSHandler.send_data
到connector.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_loop
和callback
。 Then pass io_loop
and callback
to RAMReceiver
. 然后将
io_loop
callback
给RAMReceiver
并进行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.