从高速公路 WebSocketClientProtocol 回调到另一个对象
Callbacks from autobahn WebSocketClientProtocol to another object
首先,有一个 IO
class,它在 __init__
上被传递给 asyncio 循环对象 (io = IO(loop)
),早先在主 [=42] 中创建=]. IO
class 然后在某个时候通过执行 self.socket = Socket(self)
初始化 Socket
class,以便套接字对象具有向后访问。稍后,Socket
class 初始化 Websocket
class 这是 Transport
的子 class
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket):
self.socket = socket
def open(self):
url = self.prepareUrl()
factory = WebSocketClientFactory(url, debug = False)
factory.protocol = Protocol
websocket = self.socket.loop.create_connection(factory, host=self.socket.io.options.host, port=self.socket.options.port)
self.socket.io.loop.run_until_complete(websocket)
def onOpen(self):
print('print me please!')
因此,套接字对象调用 self.transport.open()
(其中 self.transport = Websocket(self)
),它创建高速公路工厂,通过执行 self.socket.loop.create_connection()
创建异步连接,然后通过执行将 coro future 添加到循环中run_until_complete()
.
现在,这就是问题开始的地方:
高速公路工厂需要一个 class,它必须继承自 autobahn.asyncio.websocket.WebSocketClientProtocol
我的classProtocol(WebSocketClientProtocol)
有通常的:
class Protocol(WebSocketClientProtocol):
@asyncio.coroutine
def onOpen(self):
print('socket opened!')
这工作得很好,print('socket opened!')
确实打印了字符串,我的服务器也说连接已打开。
问题:
从 Protocol() class 中,当高速公路调用 onOpen() 回调时,如何让此方法调用 transport.onOpen() 方法并执行 print('print me please!')
?
好的,我修好了!使用 PyDispatch 模块轻松完成。
这是我的解决方案:
import asyncio
from pydispatch import dispatcher
from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory
from ..transport import Transport
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket):
self.socket = socket
def open(self):
url = self.prepareUrl()
factory = WebSocketClientFactory(url, debug = False)
factory.protocol = Protocol
websocket = self.socket.loop.create_connection(factory, host=self.socket.io.options.host, port=self.socket.options.port)
dispatcher.connect(self.onOpen, signal='open', sender=dispatcher.Anonymous)
self.socket.io.loop.run_until_complete(websocket)
def onOpen(self):
print('print me please!')
class Protocol(WebSocketClientProtocol):
@asyncio.coroutine
def onOpen(self):
dispatcher.send(signal='open')
更新
我有另一个 IMO 更好的解决方案。这个没有使用 PyDispatch。由于异步任务完成时有一个回调,returns user-defined 协议对象(继承自 WebSocketClientProtocol),我们可以将其用于 link 这两个对象:
import asyncio
from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory
from ..transport import Transport
class Protocol(WebSocketClientProtocol):
def __init__(self):
self.ws = None
super().__init__()
@asyncio.coroutine
def onConnect(self, response):
pass # connect handeled when SocketIO 'connect' packet is received
@asyncio.coroutine
def onOpen(self):
self.ws.onOpen()
@asyncio.coroutine
def onMessage(self, payload, isBinary):
self.ws.onMessage(payload=payload, isBinary=isBinary)
@asyncio.coroutine
def onClose(self, wasClean, code, reason):
if not wasClean:
self.ws.onError(code=code, reason=reason)
self.ws.onClose()
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket, **kwargs):
super().__init__(socket)
loop = kwargs.pop('loop', None)
self.loop = loop or asyncio.get_event_loop()
self.transport = None
self.protocol = None
self.ready = True
def open(self):
url = self.prepareUrl()
if bool(self.socket.options.query):
url = '{0}?{1}'.format(url, self.socket.options.query)
factory = WebSocketClientFactory(url=url, headers=self.socket.options.headers)
factory.protocol = Protocol
coro = self.loop.create_connection(factory, host=self.socket.options.host, port=self.socket.options.port, ssl=self.socket.options.secure)
task = self.loop.create_task(coro)
task.add_done_callback(self.onWebSocketInit)
def onWebSocketInit(self, future):
try:
self.transport, self.protocol = future.result()
self.protocol.ws = self
except Exception:
self.onClose()
def send(self, data):
self.protocol.sendMessage(payload=data.encode('utf-8'), isBinary=False)
return self
def close(self):
if self.isOpen:
self.protocol.sendClose()
return self
def onOpen(self):
super().onOpen()
self.socket.setBuffer(False)
def onMessage(self, payload, isBinary):
if not isBinary:
self.onData(payload.decode('utf-8'))
else:
self.onError('Message arrived in binary')
def onClose(self):
super().onClose()
self.socket.setBuffer(True)
def onError(self, code, reason):
self.socket.onError(reason)
首先,有一个 IO
class,它在 __init__
上被传递给 asyncio 循环对象 (io = IO(loop)
),早先在主 [=42] 中创建=]. IO
class 然后在某个时候通过执行 self.socket = Socket(self)
初始化 Socket
class,以便套接字对象具有向后访问。稍后,Socket
class 初始化 Websocket
class 这是 Transport
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket):
self.socket = socket
def open(self):
url = self.prepareUrl()
factory = WebSocketClientFactory(url, debug = False)
factory.protocol = Protocol
websocket = self.socket.loop.create_connection(factory, host=self.socket.io.options.host, port=self.socket.options.port)
self.socket.io.loop.run_until_complete(websocket)
def onOpen(self):
print('print me please!')
因此,套接字对象调用 self.transport.open()
(其中 self.transport = Websocket(self)
),它创建高速公路工厂,通过执行 self.socket.loop.create_connection()
创建异步连接,然后通过执行将 coro future 添加到循环中run_until_complete()
.
现在,这就是问题开始的地方:
高速公路工厂需要一个 class,它必须继承自 autobahn.asyncio.websocket.WebSocketClientProtocol
我的classProtocol(WebSocketClientProtocol)
有通常的:
class Protocol(WebSocketClientProtocol):
@asyncio.coroutine
def onOpen(self):
print('socket opened!')
这工作得很好,print('socket opened!')
确实打印了字符串,我的服务器也说连接已打开。
问题:
从 Protocol() class 中,当高速公路调用 onOpen() 回调时,如何让此方法调用 transport.onOpen() 方法并执行 print('print me please!')
?
好的,我修好了!使用 PyDispatch 模块轻松完成。
这是我的解决方案:
import asyncio
from pydispatch import dispatcher
from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory
from ..transport import Transport
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket):
self.socket = socket
def open(self):
url = self.prepareUrl()
factory = WebSocketClientFactory(url, debug = False)
factory.protocol = Protocol
websocket = self.socket.loop.create_connection(factory, host=self.socket.io.options.host, port=self.socket.options.port)
dispatcher.connect(self.onOpen, signal='open', sender=dispatcher.Anonymous)
self.socket.io.loop.run_until_complete(websocket)
def onOpen(self):
print('print me please!')
class Protocol(WebSocketClientProtocol):
@asyncio.coroutine
def onOpen(self):
dispatcher.send(signal='open')
更新
我有另一个 IMO 更好的解决方案。这个没有使用 PyDispatch。由于异步任务完成时有一个回调,returns user-defined 协议对象(继承自 WebSocketClientProtocol),我们可以将其用于 link 这两个对象:
import asyncio
from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory
from ..transport import Transport
class Protocol(WebSocketClientProtocol):
def __init__(self):
self.ws = None
super().__init__()
@asyncio.coroutine
def onConnect(self, response):
pass # connect handeled when SocketIO 'connect' packet is received
@asyncio.coroutine
def onOpen(self):
self.ws.onOpen()
@asyncio.coroutine
def onMessage(self, payload, isBinary):
self.ws.onMessage(payload=payload, isBinary=isBinary)
@asyncio.coroutine
def onClose(self, wasClean, code, reason):
if not wasClean:
self.ws.onError(code=code, reason=reason)
self.ws.onClose()
class Websocket(Transport):
name = 'websocket'
def __init__(self, socket, **kwargs):
super().__init__(socket)
loop = kwargs.pop('loop', None)
self.loop = loop or asyncio.get_event_loop()
self.transport = None
self.protocol = None
self.ready = True
def open(self):
url = self.prepareUrl()
if bool(self.socket.options.query):
url = '{0}?{1}'.format(url, self.socket.options.query)
factory = WebSocketClientFactory(url=url, headers=self.socket.options.headers)
factory.protocol = Protocol
coro = self.loop.create_connection(factory, host=self.socket.options.host, port=self.socket.options.port, ssl=self.socket.options.secure)
task = self.loop.create_task(coro)
task.add_done_callback(self.onWebSocketInit)
def onWebSocketInit(self, future):
try:
self.transport, self.protocol = future.result()
self.protocol.ws = self
except Exception:
self.onClose()
def send(self, data):
self.protocol.sendMessage(payload=data.encode('utf-8'), isBinary=False)
return self
def close(self):
if self.isOpen:
self.protocol.sendClose()
return self
def onOpen(self):
super().onOpen()
self.socket.setBuffer(False)
def onMessage(self, payload, isBinary):
if not isBinary:
self.onData(payload.decode('utf-8'))
else:
self.onError('Message arrived in binary')
def onClose(self):
super().onClose()
self.socket.setBuffer(True)
def onError(self, code, reason):
self.socket.onError(reason)