Python AsyncIO服务器与双客户端通信问题求助
问题分析与解决方案
你的核心问题在于服务端将完成通知发送给了上传文件的client.py,而非监听通知的receiver.py,同时服务端没有维护接收者客户端的连接列表,无法主动向receiver推送消息。以下是具体问题拆解和修复方案:
关键问题点
- 服务端逻辑错误:
handle_client中的writer属于client.py的连接,发送的响应只会回到client.py,而非receiver.py。 - client.py连接关闭过早:写入文件内容后直接关闭连接,未等待服务端响应或确保数据完全发送。
- receiver.py未标识身份:服务端无法区分上传客户端和接收客户端,不知道该把通知发给谁。
修复后的代码实现
1. 修改server.py:维护接收者连接并推送通知
import asyncio from asyncio import StreamWriter # 存储所有接收者的writer对象 receivers: set[StreamWriter] = set() async def handle_client(reader, writer): try: data = await reader.read(1024) if not data: return # 判断是否为接收者客户端 client_type = data.decode().strip() if client_type == "RECEIVER": receivers.add(writer) print("New receiver connected") # 保持连接,等待通知 await reader.read() # 阻塞直到连接关闭 receivers.remove(writer) return # 处理文件上传客户端 filename = client_type print(f"Receiving file: {filename}") with open(filename, 'wb') as file: while True: data = await reader.read(1024) if not data: break file.write(data) print(f"Received file: {filename}") # 向所有接收者发送完成通知 response = "Server has written data from client.py" for receiver_writer in receivers: try: receiver_writer.write(response.encode()) await receiver_writer.drain() except Exception: # 移除失效的连接 receivers.discard(receiver_writer) # 向上传客户端发送确认 writer.write("File uploaded successfully".encode()) await writer.drain() except asyncio.CancelledError: pass finally: writer.close() await writer.wait_closed() async def main(): server = await asyncio.start_server( handle_client, '127.0.0.1', 8888) addr = server.sockets[0].getsockname() print(f'Serving on {addr}') async with server: await server.serve_forever() if __name__ == '__main__': asyncio.run(main())
2. 修改client.py:正确处理连接关闭
import asyncio async def send_file(filename, server_host, server_port): reader, writer = await asyncio.open_connection(server_host, server_port) # 发送文件名 writer.write(filename.encode()) await writer.drain() with open(filename, 'rb') as file: while True: data = file.read(1024) if not data: break writer.write(data) await writer.drain() # 确保数据发送完成 # 等待服务端确认 response = await reader.read(1024) print(f"Server response: {response.decode()}") writer.close() await writer.wait_closed() if __name__ == '__main__': server_host = '127.0.0.1' server_port = 8888 filename = 'temp.txt' asyncio.run(send_file(filename, server_host, server_port))
3. 修改receiver.py:标识身份并持续监听
import asyncio async def receive_data(): reader, writer = await asyncio.open_connection('127.0.0.1', 8888) # 发送身份标识,告诉服务端自己是接收者 writer.write("RECEIVER".encode()) await writer.drain() print("Waiting for server notifications...") while True: response = await reader.read(1024) if not response: break message = response.decode() print(f"Received: {message}") print("Connection closed by server") writer.close() await writer.wait_closed() async def main(): await receive_data() if __name__ == '__main__': asyncio.run(main())
使用步骤
- 先启动
server.py - 启动
receiver.py(可启动多个) - 运行
client.py上传文件,此时所有运行的receiver都会收到完成通知
内容的提问来源于stack exchange,提问作者ysingh-1636
相关产品推荐
相关产品推荐

