It's being a hard crash course for me in the last few weeks learning asyncio Stream library to build a server.
After solving a lot of small issues, I found one that simply doesn't make any sense. I am trying to start a bunch of servers (using loop.create_server) but for some reason, all servers work as the last spawned server. I even wrote a small program to show what I am talking about:
import asyncio
LST_SERVERS = [{'name': 'Server1', 'port': 10051},
{'name': 'Server2', 'port': 10052},
{'name': 'Server3', 'port': 10053}]
async def print_test():
print('test')
class Protocol1(asyncio.Protocol):
def __init__(self, name):
print('starting')
self.name = name
def connection_made(self, transport):
self.transport = transport
self.peername = transport.get_extra_info("peername")
print(f'New Connection on Protocol1: {self.peername}')
def data_received(self, data):
print(f'Data received: {data.decode("utf-8")}')
self.transport.write(f'Hi, I am {self.name}'.encode('utf-8'))
def connection_lost(self, ex):
print(f'Disconnected {self.peername}')
class Protocol2(asyncio.Protocol):
def __init__(self, name):
print('starting')
self.name = name
def connection_made(self, transport):
self.transport = transport
self.peername = transport.get_extra_info("peername")
print(f'New Connection on Protocol2: {self.peername}')
def data_received(self, data):
print(f'Data received: {data.decode("utf-8")}')
self.transport.write(f'Hi, I am {self.name}'.encode('utf-8'))
def connection_lost(self, ex):
print(f'Disconnected {self.peername}')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.create_task(print_test())
for server in LST_SERVERS:
print(f'Starting {server["name"]} on port {server["port"]}')
name = server["name"]
if name == 'Server1':
protocol = Protocol1
else:
protocol = Protocol2
server = loop.run_until_complete(
loop.create_server(protocol_factory=lambda: protocol(name),
host='0.0.0.0',
port=server['port']))
try:
loop.run_forever()
except KeyboardInterrupt:
print('Server stoped')
finally:
loop.close()
I have a list of servers to start. Each one with a different port and a different name. I also have 2 different protocols (that are pretty much equal). When I run it, the first server would use the first protocol and the rest would use the second protocol (because of the line 54 condition). But look what happens after I run it and test using netcat all ports (to make it easy to understand, I used arrows to point what was input and what was output):
nc localhost 10051
> Hi 10051
< Hi, I am Server3^C
nc localhost 10052
> Hi 10052
< Hi, I am Server3^C
nc localhost 10053
> Hi 10053
< Hi, I am Server3
All of them are Server3??? Why?
Also, this is the program output:
Starting Server1 on port 10051
test
Starting Server2 on port 10052
Starting Server3 on port 10053
starting
New Connection on Protocol2: ('127.0.0.1', 47922)
Data received: Hi 10051
Disconnected ('127.0.0.1', 47922)
starting
New Connection on Protocol2: ('127.0.0.1', 34088)
Data received: Hi 10052
Disconnected ('127.0.0.1', 34088)
starting
New Connection on Protocol2: ('127.0.0.1', 41868)
Data received: Hi 10053
WTF? They are all Protocol2! Am I missing something? Is there another way to start a bunch of servers? I used this post on a maillist as a reference for running my code