asyncio streams 的 Python 3.7 文档包含一个 TCP echo 服务器示例:
import asyncio
async def handle_echo(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"Received {message!r} from {addr!r}")
print(f"Send: {message!r}")
writer.write(data)
await writer.drain()
print("Close the connection")
writer.close()
async def main():
server = await asyncio.start_server(
handle_echo, '127.0.0.1', 8888)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
asyncio.run(main())
这是我特别感兴趣的片段:
async with server:
await server.serve_forever()
因此,我们正在做两件事:
- 我们将
asyncio.Server
用作上下文管理器,对于该上下文管理器,(从该页面("保证 Server 对象已关闭,并且在 async with 语句完成时不接受新连接"。 - 我们打电话给
Server.serve_forever()
.这通常会开始侦听(如果尚未启动(,并确保在取消协程时关闭服务器。当我们到达这些行时,我们已经调用了start_server
(默认start_serving=True
(,因此唯一的效果是确保服务器关闭。
似乎这些基本上在做同样的事情。为什么示例中包含这两行?最合理的实际应用是否可能同时包含两者?
答案是不必要的冗余可以在这里看到。如果服务器已接受连接,则可以调用 serve_forever
方法。
在Server
对象方法说明中,serve_forever
协程示例如下所示:
async def client_connected(reader, writer):
# Communicate with the client with
# reader/writer streams. For example:
await reader.readline()
async def main(host, port):
srv = await asyncio.start_server(
client_connected, host, port)
await srv.serve_forever()
asyncio.run(main('127.0.0.1', 0))
更多信息可以在官方文档中找到。