引言
以往在 socket 程序开发中,一直使用 Python 的 socket 库进行编程。为了提高编程效率和运行效率,对程序进行了重构,准备用异步 io 库替换原来的socket库。为此,在官网例子的基础上,结合具体的需求,逐步对其修改形成自己的异步 socket 程序。这里将整个过程写下来,供有需要的开发者参考。
基础资料
我们所依据的是官网手册中给出的例子,相关链接是:https://docs.python.org/zh-cn/3.7/library/asyncio-stream.html#examples 该网页给出了两个例子,一个是客户端,另一个是服务端。其功能是服务端将接收到的客户端消息再发还给客户端。这两个程序的功能和结构都比较简单,其中客户端程序是:
import asyncio
async def tcp_echo_client(message):
reader, writer = await asyncio.open_connection(
'127.0.0.1', 8888)
print(f'Send: {message!r}')
writer.write(message.encode())
data = await reader.read(100)
print(f'Received: {data.decode()!r}')
print('Close the connection')
writer.close()
asyncio.run(tcp_echo_client('Hello World!'))
服务端程序是:
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())
除了加了几个空行,以符合 PEP8 的规定以外,这两个程序完全是从官网复制来的,未做其他修改。
集成开发环境使用的是Pycharm。运行以后,客户端的结果显示是:
Send: 'Hello World!'
Received: 'Hello World!'
Close the connection
Process finished with exit code 0
服务端显示的运行结果为:
Serving on ('127.0.0.1', 8888)
Received 'Hello World!' from ('127.0.0.1', 50557)
Send: 'Hello World!'
Close the connection
需求
我们要在上述程序的基础上,修改服务端程序,实现如下需求:
1. 服务端的 socket 程序部分(简称socket程序)能够同时服务于多个客户端的连接;
2. 客户端和服务端都能保持长时间连接和数据收发;
3. 服务端的 socket 程序不处理接收到的数据,而是通过其他模块(简称处理模块)的接收队列转发后处理;
4. 处理结果通过另一个队列发送到 socket 程序,socket 程序检查标识,转发到相应连接客户端;
5. 处理模块可以集中处理来自多个 socket 实例的数据,并能够按照原有路由将处理结果发回,
下面的两篇博文中,将对上述官网中的程序逐步做出修改,最终满足这些需求。