客户端连接后通过 ws 从另一个 class 发送数据
Send data from an other class through ws after client connected
我想在客户端连接后立即通过 websockets 发送数据。
数据位于 Websocket 处理程序之外的其他位置。我如何才能将数据发送给客户端?
服务器应该持有循环和处理程序。在连接器中,我连接到一个 tcp 套接字以从某些硬件中获取数据。我预计一次打开的 Websocket 不会超过 6 个。数据以流的形式从 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"[=12=]")
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. 将当前 运行 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.然后修改connector.py
中的main_task
函数接收io_loop
和callback
。然后将 io_loop
和 callback
传递给 RAMReceiver
。
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)
...
我想在客户端连接后立即通过 websockets 发送数据。 数据位于 Websocket 处理程序之外的其他位置。我如何才能将数据发送给客户端?
服务器应该持有循环和处理程序。在连接器中,我连接到一个 tcp 套接字以从某些硬件中获取数据。我预计一次打开的 Websocket 不会超过 6 个。数据以流的形式从 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"[=12=]")
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. 将当前 运行 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.然后修改connector.py
中的main_task
函数接收io_loop
和callback
。然后将 io_loop
和 callback
传递给 RAMReceiver
。
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)
...