asyncio.StreamWriter暂停无法发送请求,如何解决?
问题分析与修复方案
问题原因
从你提供的StreamWriter状态能明确看出:
- 循环后StreamReader标记为
paused,且缓存了173203字节未处理数据 - 核心原因是TCP连接的接收缓冲区被未读取的数据填满,触发了asyncio的流暂停机制。当StreamReader的缓冲区达到高水位线时,会自动暂停读取操作;同时TCP滑动窗口会因接收端未处理数据而收缩,最终导致发送端无法继续写入数据。
修复步骤
你需要在发送数据的同时,持续读取并处理(或直接丢弃)接收端的数据,避免缓冲区被填满。具体实现如下:
1. 编写后台读取协程
创建独立协程持续读取StreamReader的数据,哪怕不需要这些数据,也要清空缓冲区:
async def drain_reader(reader): try: while True: # 按固定大小读取数据,可根据实际场景调整 data = await reader.read(4096) if not data: # 读取到空数据,说明连接已关闭 break # 若无需使用数据,此处直接跳过;有业务需求则添加处理逻辑 except Exception as e: # 处理连接异常,比如断开、超时等 print(f"读取异常: {e}")
2. 并发执行发送与读取逻辑
在启动发送循环前,通过asyncio.create_task启动后台读取任务,确保发送和读取操作同时进行:
# 假设已通过asyncio.open_connection或类似方法获取到reader和writer async def main(): reader, writer = await asyncio.open_connection('your_host', your_port) # 启动后台读取任务,持续清空接收缓冲区 asyncio.create_task(drain_reader(reader)) request_screen = True while request_screen: writer.write(b'screenshare') await writer.drain() # 添加适当延迟,避免高频发送导致网络压力 await asyncio.sleep(0.05) # 关闭连接并释放资源 writer.close() await writer.wait_closed() asyncio.run(main())
额外注意事项
- 处理连接关闭:当
reader.read()返回空字节时,说明对方已关闭连接,此时应终止发送循环并清理资源。 - 调整读取块大小:
4096是常规缓冲区大小,可根据业务场景调整为更合适的值。 - 控制发送频率:无延迟循环发送可能导致网络拥堵,通过
asyncio.sleep()合理控制发送间隔。
内容的提问来源于stack exchange,提问作者Data Reset
相关产品推荐
相关产品推荐

