在学习asyncio的时候,一直想写一个在学习进程的时候的那种双全工tcp通讯客户端,官方文档的示例也只是单工的,研究了一段时间,总算搞定,特记录一下。
在理解task和future过程中踩过不少坑,task对象创建成功之后就直接注册到了eventloop中了,主进程中需要遇到await等待(await可以理解成执行并切换下一个任务),便可自动进入到task对象中。
import asyncio
async def sleep1():
while True:
print(1)
await asyncio.sleep(1)
async def sleep2():
while True:
print(2)
await asyncio.sleep(1)
async def main():
task1=asyncio.create_task(sleep1())
task2=asyncio.create_task(sleep2())
#1.添加一个等待事件便可运行
while 1:
await asyncio.sleep(0)
#2.用await gather并发运行也可以,
# await asyncio.gather(task1,task2)
# await 用来执行协程(task,future)任务,并开始切换,直到其执行的任务有了return返回之后才开始继续向下执行
asyncio.run(main())
通过上面的运行机制 将tcp流的read对象和send对象封装成相应的协程函数,实现双全工的客户端。
再发送信息中,asyncio 并没有协程的input输入,所以需要将同步的input转换成异步的,采用loop.run_in_executor可以转换,具体使用可以查看文档。
loop=asyncio.get_running_loop()
loop.run_in_executor(None, func)
完成版的客户端代码如下:
async def tcp_echo_client():
reader, writer = await asyncio.open_connection(
'127.0.0.1', 8888)
async def sendd():
loop=asyncio.get_running_loop()
while 1:
message=await loop.run_in_executor(None, input_d) #将同步的input转化成异步的
writer.write(message.encode())
async def readd():
while 1:
data = await reader.read(100)
print(f'收到的信息:: {data.decode()}')
def input_d(): # asyncio没有异步的input,定义一个并将其转化成写成对象
return input("输入一个信息:\n")
await asyncio.gather(readd(),sendd())
asyncio.run(tcp_echo_client())