首页 > 解决方案 > 使用不同的协议启动多个服务器(asyncio Stream)

问题描述

在过去的几周里,学习 asyncio Stream 库来构建服务器对我来说是一门很难的速成课程。

在解决了很多小问题之后,我发现一个根本没有任何意义的问题。我正在尝试启动一堆服务器(使用loop.create_server),但由于某种原因,所有服务器都作为最后一个生成的服务器工作。我什至写了一个小程序来显示我在说什么:

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()

我有一个要启动的服务器列表。每个都有不同的端口和不同的名称。我也有 2 种不同的协议(几乎相等)。当我运行它时,第一个服务器将使用第一个协议,其余的将使用第二个协议(因为第 54 行条件)。但是看看我运行它并使用 netcat 所有端口进行测试后会发生什么(为了便于理解,我使用箭头来指示输入和输出的内容):

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

都是Server3???为什么?

此外,这是程序输出:

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

怎么回事?他们都是Protocol2!我错过了什么吗?还有另一种方法来启动一堆服务器吗?我在邮件列表中使用了这篇文章作为运行代码的参考

标签: python-3.xpython-asyncio

解决方案


推荐阅读