多线程Socket客户端经中心服务器点对点文件传输的问题排查
让我帮你梳理下代码里的几个关键问题,这些就是导致你现在看不到接收方收到信息、文件传输失败的核心原因:
1. 端口完全不匹配(最直观的错误)
你的发送方服务器绑定的是12345端口,但接收方客户端却尝试连接12346端口——这完全是两个毫无关联的端口,接收方根本连不上发送方的服务器。你需要把两边的端口统一,要么都用12345,要么都用12346。
2. 接收方缺失中心服务器消息的处理逻辑
你提到中心服务器已经向接收方(k对应的连接)发送了发送方的IP和文件名,但你的接收方线程代码里完全没有这段消息的接收逻辑!接收方现在的逻辑是直接去创建客户端连接,但它根本不知道要连哪个IP、要保存成什么文件名。
你需要在接收方的代码里先从中心服务器的连接中读取到addr[0]+' '+filename这个消息,解析出IP和文件名后,再去发起连接。比如:
# 先从中心服务器接收发送方IP和文件名 data = k.recv(1024).decode() sender_ip, filename = data.split() # 再用解析出的参数调用create_client self.create_client(sender_ip, filename)
3. 发送方服务器的文件发送逻辑错误
在create_server函数里,你用监听套接字sock来发送文件数据——这是完全错误的!sock是用来监听新连接的套接字,当conn, addr = sock.accept()成功建立连接后,你应该用新生成的conn套接字来和接收方通信。而且这里的select完全没必要,直接循环读取文件并发送给conn即可:
修正后的create_server核心代码:
def create_server(self, ip, path): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定0.0.0.0允许所有IP访问,同一设备用127.0.0.1也可以 sock.bind((ip, 12345)) print("server created") sock.listen(1) conn, addr = sock.accept() # 等待接收方连接 print(f"Connected to {addr}") with open(path, "rb") as file: print("file opened") while True: chunk = file.read(4096) print("chunk read") if not chunk: break # 读取到文件末尾 conn.sendall(chunk) # 用conn发送,而非监听套接字sock print("chunk sent") print("Transfer complete") conn.close() sock.close()
4. 同一设备本地IP绑定的小坑
如果你的发送方服务器绑定的是设备的外部局域网IP,同一设备内部的客户端连接可能会出现异常(部分系统默认不会走回环路由)。建议发送方服务器绑定0.0.0.0(允许所有来源连接)或者127.0.0.1(仅限本地连接),这样同一设备的客户端肯定能连上。
5. 线程同步问题
发送方创建服务器需要完成bind、listen等步骤,需要一点时间。如果接收方在服务器还没准备好的时候就去连接,会导致连接失败。你可以在发送方创建完服务器并监听后,通过中心服务器给接收方发一个“服务器已就绪”的信号,或者在接收方连接时加入简单的重试逻辑。
内容的提问来源于stack exchange,提问作者SajanGohil

