如何通过asyncio将用户输入传入客户端连接以发送至服务器?
解决asyncio客户端发送用户输入消息的问题
我来帮你搞定这个问题!在asyncio的异步模型里,直接用input()会阻塞事件循环,所以得用点技巧把用户输入和网络发送结合起来。下面是具体的实现方案和修改后的代码:
核心思路
- 首先在
ChatClient类里保存好transport实例,这样后续才能调用它发送数据; - 写一个异步函数专门处理用户输入,用
run_in_executor把同步的input()放到线程池执行,避免阻塞事件循环; - 客户端连接成功后,启动这个输入处理任务,让它和网络接收逻辑一起在事件循环里运行。
修改后的完整代码
import asyncio import zen_utils import json from struct import * class ChatClient(asyncio.Protocol): def __init__(self): self.transport = None def connection_made(self, transport): # 保存transport实例,用于后续发送数据 self.transport = transport print("已连接到服务器,可以开始发送消息了") # 启动发送消息的异步任务 asyncio.create_task(self.send_messages()) def data_received(self, data): # 处理服务器发来的消息,这里保留你原来的逻辑 print(f"收到服务器消息: {data.decode('utf-8')}") def connection_lost(self, exc): print("与服务器断开连接") # 断开连接后停止事件循环 asyncio.get_running_loop().stop() async def send_messages(self): while True: try: # 用run_in_executor避免input()阻塞事件循环 user_input = await asyncio.get_running_loop().run_in_executor( None, input, "请输入消息(输入exit退出): " ) if user_input.lower() == 'exit': self.transport.close() break # 根据你的需求处理消息格式,比如转成json或者用struct打包 # 这里举个json的例子,你可以换成自己需要的格式 message = json.dumps({"content": user_input}).encode('utf-8') self.transport.sendall(message) except Exception as e: print(f"发送消息出错: {e}") break async def main(): # 替换成你的服务器地址和端口 host, port = '127.0.0.1', 8888 loop = asyncio.get_running_loop() # 创建客户端连接 transport, protocol = await loop.create_connection( ChatClient, host, port ) # 让事件循环一直运行,直到断开连接 await asyncio.Event().wait() if __name__ == "__main__": asyncio.run(main())
关键细节解释
- 保存transport:在
connection_made里把transport存到实例变量里,这样send_messages才能调用它的sendall方法发送数据; - 异步处理用户输入:用
run_in_executor把同步的input()放到线程池执行,这样事件循环不会被阻塞,还能同时处理服务器发来的消息; - 退出逻辑:添加了输入
exit退出的逻辑,你可以根据自己的需求调整; - 消息格式:这里用json做了示例,你可以根据服务器的要求换成struct打包或者其他格式,只要把最终的字节数据传给
sendall就行。
这样修改后,你的客户端就能一边接收服务器消息,一边处理用户输入并发送了。
内容的提问来源于stack exchange,提问作者Jackson Michaels
相关产品推荐
相关产品推荐

