简体   繁体   English

如何使用 asyncio.Protocol 在 python asyncio 中创建和运行两个或多个(多个)服务器

[英]How to create and run two or more (multiple) servers in python asyncio with asyncio.Protocol

I would like to run two simple TCP servers in one script using asyncio in python (Python 3.9.9).我想在 python(Python 3.9.9)中使用 asyncio 在一个脚本中运行两个简单的 TCP 服务器。 Each server runs on a different port, obviously.显然,每台服务器都在不同的端口上运行。 I am having trouble with the correct syntax to use to create and launch the two servers at the same time.我在使用正确的语法来同时创建和启动两个服务器时遇到了问题。 Below is what I have so far, but I keep getting RuntimeError: This event loop is already running.以下是我到目前为止所拥有的,但我不断收到 RuntimeError: This event loop already running。

I have seen the way to do this using just a function and loop.start_server, but I need to use the asyncio.Protocol class so that I can have access to the callbacks for conection_made and connection_lost.我已经看到仅使用 function 和 loop.start_server 来执行此操作的方法,但我需要使用 asyncio.Protocol class 以便我可以访问 conection_made 和 connection_lost 的回调。 I don't know if I need loop.create_server or some other syntax, but whatever I am doing is obviously wrong.我不知道我是否需要 loop.create_server 或其他一些语法,但无论我做什么显然都是错误的。 So how do I do this with asyncio.Protocol?那么我该如何使用 asyncio.Protocol 做到这一点呢?

Note: Both of these servers are meant to run forever.注意:这两个服务器都意味着永远运行。 Clients may connect and disconnect butthe servers should run forever.客户端可以连接和断开连接,但服务器应该永远运行。

###############################################################################
# echoserver.py
# Simple code to run EchoServer on two ports simultaneously
###############################################################################
import asyncio

FIRST_PROCESS_PORT =14401
SECOND_PROCESS_PORT =14402

class MyLogger(object):
    def info(self,s):
        print(s)
logger = MyLogger()

#
# EchoServer class
#
class EchoServer(asyncio.Protocol):
    def __init__(self):
        self.client_info=None

    # Begin asyncio.Protocol overrides
    def connection_made(self,transport):
        self.transport = transport
        self.client_info = self.transport.get_extra_info('peername')
        logger.info('connection_made from: %s' % self.client_info)

    def connection_lost(self, reason):
        logger.info( 'connection_lost: %s | %s' % (self.client_info, reason))

    def data_received(self,data):
        print("Received: %s" % str(data))
        self.transport.write(data)

async def main():
    global server1
    global server2

    loop = asyncio.get_running_loop()

    factory1 = await loop.create_server(lambda: EchoServer(),"localhost",FIRST_PROCESS_PORT)
    factory2 = await loop.create_server(lambda: EchoServer(),"localhost",SECOND_PROCESS_PORT)
    server1 = await loop.run_until_complete(factory1)
    server2 = await loop.run_until_complete(factory2)

    async with server1, server2:
        await asyncio.gather(server1.run_forever(),server2.run_forever())

    print("Main done");

###################
# main code here
###################
if __name__ == "__main__":
    asyncio.run(main())
    print("Done");

I've made some simple rearrangements to make the server work on two ports:我做了一些简单的重新安排,使服务器在两个端口上工作:

###############################################################################
# echoserver.py
# Simple code to run EchoServer on two ports simultaneously
###############################################################################
import asyncio

FIRST_PROCESS_PORT = 14401
SECOND_PROCESS_PORT = 14402


class MyLogger(object):
    def info(self, s):
        print(s)


logger = MyLogger()


class EchoServer(asyncio.Protocol):
    def __init__(self):
        self.client_info = None

    # Begin asyncio.Protocol overrides
    def connection_made(self, transport):
        self.transport = transport
        self.client_info = self.transport.get_extra_info("peername")
        logger.info(f"connection_made from: {self.client_info}")

    def connection_lost(self, reason):
        logger.info("connection_lost: %s | %s" % (self.client_info, reason))

    def data_received(self, data):
        print("Received: %s" % str(data))
        self.transport.write(data)


async def main():
    loop = asyncio.get_running_loop()

    server1 = await loop.create_server(
        EchoServer, "0.0.0.0", FIRST_PROCESS_PORT
    )
    server2 = await loop.create_server(
        EchoServer, "0.0.0.0", SECOND_PROCESS_PORT
    )

    # serve forever
    async with server1, server2:
        while True:
            await asyncio.sleep(3600)


if __name__ == "__main__":
    asyncio.run(main())

This will create two ports on all interfaces ( 0.0.0.0 ), but you can change it to localhost .这将在所有接口 ( 0.0.0.0 ) 上创建两个端口,但您可以将其更改为localhost

On other terminal if you run:在其他终端上运行:

echo "Hello World" | nc -N <your IP address> 14401
echo "Hello World" | nc -N <your IP address> 14402

the server responds:服务器响应:

connection_made from: ('XXX', 41760)
Received: b'Hello World\n'
connection_lost: ('XXX', 41760) | None
connection_made from: ('XXX', 32872)
Received: b'Hello World\n'
connection_lost: ('XXX', 32872) | None

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM