[英]Autobahn Asyncio ReconnectingClientFactory
I would like to make a ReconnectingClientFactory
with asyncio. 我想用asyncio创建一个ReconnectingClientFactory
。 In particular to handle the case that the server is not available when the client is started in which case the ReconnectingClientFactory
will keep trying. 特别是为了处理客户端启动时服务器不可用的情况,在这种情况下ReconnectingClientFactory
将继续尝试。 That is something that the asyncio.events.create_connection
does not do. 这是asyncio.events.create_connection
不能做的事情。
Concretely: 具体来说:
The EchoClient example would be fine. EchoClient示例没问题。 The crux is how the connection is made. 关键是如何建立联系。
factory = EchoClientFactory('ws://127.0.0.1:5678')
connectWS(factory)
in the case of the twisted version with ReconnectingClientFactory
. 在使用ReconnectingClientFactory
的扭曲版本的情况下。
Vs VS
factory = EchoClientFactory(u"ws://127.0.0.1:5678")
factory.protocol = SecureServerClientProtocol
loop = asyncio.get_event_loop()
# coro = loop.create_connection(factory, 'ws_server', 5678)
coro = loop.create_connection(factory, '127.0.0.1', 5678)
loop.run_until_complete(asyncio.wait([
alive(), coro
]))
loop.run_forever()
loop.close()
Or similar with the asycnio version. 或者类似于asycnio版本。
The problem is that in the asyncio version the connection is established by asyncio.events.create_connection
which simply fails if the server is not available. 问题是在asyncio版本中,连接是由asyncio.events.create_connection
建立的,如果服务器不可用,它就会失败。
How can I reconcile the two? 我怎样才能调和这两个?
Many thanks 非常感谢
I think I get what you want. 我想我得到了你想要的东西。 Here's the code and example based on asyncio TCP echo client protocol example . 这是基于asyncio TCP echo客户端协议示例的代码和示例 。
import asyncio
import random
class ReconnectingTCPClientProtocol(asyncio.Protocol):
max_delay = 3600
initial_delay = 1.0
factor = 2.7182818284590451
jitter = 0.119626565582
max_retries = None
def __init__(self, *args, loop=None, **kwargs):
if loop is None:
loop = asyncio.get_event_loop()
self._loop = loop
self._args = args
self._kwargs = kwargs
self._retries = 0
self._delay = self.initial_delay
self._continue_trying = True
self._call_handle = None
self._connector = None
def connection_lost(self, exc):
if self._continue_trying:
self.retry()
def connection_failed(self, exc):
if self._continue_trying:
self.retry()
def retry(self):
if not self._continue_trying:
return
self._retries += 1
if self.max_retries is not None and (self._retries > self.max_retries):
return
self._delay = min(self._delay * self.factor, self.max_delay)
if self.jitter:
self._delay = random.normalvariate(self._delay,
self._delay * self.jitter)
self._call_handle = self._loop.call_later(self._delay, self.connect)
def connect(self):
if self._connector is None:
self._connector = self._loop.create_task(self._connect())
async def _connect(self):
try:
await self._loop.create_connection(lambda: self,
*self._args, **self._kwargs)
except Exception as exc:
self._loop.call_soon(self.connection_failed, exc)
finally:
self._connector = None
def stop_trying(self):
if self._call_handle:
self._call_handle.cancel()
self._call_handle = None
self._continue_trying = False
if self._connector is not None:
self._connector.cancel()
self._connector = None
if __name__ == '__main__':
class EchoClientProtocol(ReconnectingTCPClientProtocol):
def __init__(self, message, *args, **kwargs):
super().__init__(*args, **kwargs)
self.message = message
def connection_made(self, transport):
transport.write(self.message.encode())
print('Data sent: {!r}'.format(self.message))
def data_received(self, data):
print('Data received: {!r}'.format(data.decode()))
def connection_lost(self, exc):
print('The server closed the connection')
print('Stop the event loop')
self._loop.stop()
loop = asyncio.get_event_loop()
client = EchoClientProtocol('Hello, world!', '127.0.0.1', 8888, loop=loop)
client.connect()
loop.run_forever()
loop.close()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.