服务器端事件是一种http协议;并且您可能在任何特定时刻都有任何并发http请求在运行,如果没有人连接或几十个,您可能有零个。这种细微差别全部包含在两个sse.serve和sse.Handler构造中;前者代表一个单一的侦听端口,将每个单独的客户请求分派给后者。
此外,sse.Handler.handle_request()为每个客户端调用一次,并且一旦该协程序终止,客户端就会断开连接。在你的代码中,该协程立即终止,所以客户端看到一个“工作”事件。所以,我们需要等待,或多或少永远。我们可以通过yield from来做到这一点asyncio.Future()。
第二个问题是,我们需要以某种方式获得对SSEHandler()的所有单独实例的控制权,并在其中每个方法上使用send()方法。那么,我们可以让他们自己注册他们的handle_request()方法;通过将每个处理程序实例添加到一个将它们映射到它们正在等待的未来的字典中。
class SSEHandler(sse.Handler):
_instances = {}
@asyncio.coroutine
def handle_request(self):
self.send('Working')
my_future = asyncio.Future()
SSEHandler._instances[self] = my_future
yield from my_future
现在,对事件发送到每一个聆听我们刚刚访问所有在我们创建的字典中注册的SSEHandler实例和对每一个使用send()。
class SSEHandler(sse.Handler):
#...
@classmethod
def broadcast(cls, message):
for instance, future in cls._instances.items():
instance.send(message)
class Telnet(asyncio.Protocol):
#...
def data_received(self, data):
#...
SSEHandler.broadcast(data.decode('ascii'))
最后,当telnet连接关闭时,您的代码将退出。这很好,但我们当时也应该清理。幸运的是,这只是一个为所有的处理程序
class SSEHandler(sse.Handler):
#...
@classmethod
def abort(cls):
for instance, future in cls._instances.items():
future.set_result(None)
cls._instances = {}
class Telnet(asyncio.Protocol):
#...
def connection_lost(self, esc):
print("Connection lost!")
SSEHandler.abort()
telnet_server.close()
的所有期货的设定结果的事这里是万一一个完整的,工作转储我的例证并不明显。
import asyncio
import sse
loop = asyncio.get_event_loop()
sse_host, sse_port = '0.0.0.0', 8888
class Telnet(asyncio.Protocol):
def connection_made(self, transport):
print("Connection received!");
self.transport = transport
def data_received(self, data):
SSEHandler.broadcast(data.decode('ascii'))
def connection_lost(self, esc):
print("Connection lost!")
SSEHandler.abort()
telnet_server.close()
class SSEHandler(sse.Handler):
_instances = {}
@classmethod
def broadcast(cls, message):
for instance, future in cls._instances.items():
instance.send(message)
@classmethod
def abort(cls):
for instance, future in cls._instances.items():
future.set_result(None)
cls._instances = {}
@asyncio.coroutine
def handle_request(self):
self.send('Working')
my_future = asyncio.Future()
SSEHandler._instances[self] = my_future
yield from my_future
sse_server = sse.serve(SSEHandler, sse_host, sse_port)
telnet_server = loop.run_until_complete(loop.create_server(Telnet, '0.0.0.0', 7777))
loop.run_until_complete(sse_server)
loop.run_until_complete(telnet_server.wait_closed())