我想在 app.py 上使用 asyncio 创建两个协议(TcpClient 和 UdpServer),其中 TcpClient 将与 server.py 和 UdpServer 作为 UDP 服务器建立持久连接:
我需要什么:
a) 两种协议进行通信:互相调用方法。这仅适用于第一个连接。如果 TcpClient 重新连接,它不能再次发送字符串“send to tcp”。来自 UdpServer。我检查print(self)
并 TcpClient 创建了一个新实例,旧实例仍然存在但没有连接,但我不知道如何重构它。我认为我以错误的方式使用 asyncio。
b) 当 TcpClient 与 server.py 断开连接时,等待 5s 并尝试重新连接,以此类推。我尝试使用call_later()
asyncio,但我认为有一种本地方法可以做到这一点,而不是一种技巧。
c)当我启动 app.py 时,如果 TcpClient 无法连接,我想在 5 秒后尝试重新连接,依此类推。我不知道该怎么做。
这里是我对 app.py server.py 的示例测试。server.py 仅用于测试 - 这将是另一种语言。
只是说我尝试过:
1)当我启动 app.py 并且 server.py 关闭时,app.py 不要重试。
2)当app.py连接到server.py并且服务器关闭并快速启动时,TcpClient重新连接,但我不能更多地在新实例上连接其他方法并发送字符串“send to tcp”。到 server.py,只是旧的,没有更多的连接。
3)如果我asyncio.async()
改用,run_until_complete()
我不能从其他协议调用方法。
我把 app.py 和 server.py 放在这里,所以你可以复制并运行测试。
我ncat localhost 9000 -u -v
用来发送字符串“send to tcp.”。该字符串需要打印在 UdpServer 类上并传递给 TcpClient 类的方法 send_data_to_tcp,该方法会将字符串发送到 server.py。<- 这在第一次重新连接 tcpClient 后不起作用。
我正在使用 Python 3.4.0。
太感谢了。
应用程序.py:
import asyncio
#TCP client
class TcpClient(asyncio.Protocol):
message = 'Testing'
def connection_made(self, transport):
self.transport = transport
self.transport.write(self.message.encode())
print('data sent: {}'.format(self.message))
server_udp[1].tcp_client_connected()
def data_received(self, data):
self.data = format(data.decode())
print('data received: {}'.format(data.decode()))
if self.data == 'Testing':
server_udp[1].send_data_to_udp(self.data)
def send_data_to_tcp(self, data):
self.transport.write(data.encode())
def connection_lost(self, exc):
msg = 'Connection lost with the server...'
info = self.transport.get_extra_info('peername')
server_udp[1].tcp_client_disconnected(msg, info)
#UDP Server
class UdpServer(asyncio.DatagramProtocol):
CLIENT_TCP_TIMEOUT = 5.0
def __init__(self):
self.client_tcp_timeout = None
def connection_made(self, transport):
print('start', transport)
self.transport = transport
def datagram_received(self, data, addr):
self.data = data.strip()
self.data = self.data.decode()
print('Data received:', self.data, addr)
if self.data == 'send to tcp.':
client_tcp[1].send_data_to_tcp(self.data)
def connection_lost(self, exc):
print('stop', exc)
def send_data_to_udp(self, data):
print('Receiving on UDPServer Class: ', (data))
def connect_client_tcp(self):
coro = loop.create_connection(TcpClient, 'localhost', 8000)
#client_tcp = loop.run_until_complete(coro)
client_tcp = asyncio.async(coro)
def tcp_client_disconnected(self, data, info):
print(data)
self.client_tcp_info = info
self.client_tcp_timeout = asyncio.get_event_loop().call_later(self.CLIENT_TCP_TIMEOUT, self.connect_client_tcp)
def tcp_client_connected(self):
if self.client_tcp_timeout:
self.client_tcp_timeout.cancel()
print('call_later cancel.')
loop = asyncio.get_event_loop()
#UDP Server
coro = loop.create_datagram_endpoint(UdpServer, local_addr=('localhost', 9000))
#server_udp = asyncio.Task(coro)
server_udp = loop.run_until_complete(coro)
#TCP client
coro = loop.create_connection(TcpClient, 'localhost', 8000)
#client_tcp = asyncio.async(coro)
client_tcp = loop.run_until_complete(coro)
loop.run_forever()
服务器.py:
import asyncio
class EchoServer(asyncio.Protocol):
def connection_made(self, transport):
peername = transport.get_extra_info('peername')
print('connection from {}'.format(peername))
self.transport = transport
def data_received(self, data):
print('data received: {}'.format(data.decode()))
self.transport.write(data)
# close the socket
#self.transport.close()
#def connection_lost(self):
# print('server closed the connection')
loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServer, 'localhost', 8000)
server = loop.run_until_complete(coro)
print(server)
print(dir(server))
print(dir(server.sockets))
print('serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
print("exit")
finally:
server.close()
loop.close()