You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python基于Socket传输文件完成后 服务端挂起无法退出接收循环

问题根因

TCP是无内置消息边界的面向字节流协议,服务端recv()只有在对端完全关闭连接、收到TCP FIN包的时候,才会返回空字节触发退出逻辑。
当前实现中,客户端把全部文件内容发送完成后,既没有告知服务端“传输已经结束”,也没有关闭自身的套接字写通道,连接一直处于“可双向收发数据”的状态,服务端自然会一直阻塞在recv()调用上,永远等不到空返回值。

最小改动修复方案

只需要在客户端发送完全部文件数据后,调用套接字的shutdown方法半关闭写通道即可——这个操作只会告知对端“我这边不会再发送任何新数据”,不会影响后续客户端接收服务端的响应,不需要直接关闭整个套接字。
修改后的客户端代码:

def download_file(self, file_name):
    with open(file_name, "rb") as file:
        while True:
            l = file.read(64)
            if not l:
                break
            self.s.sendall(l)
    # 所有数据发送完成,半关闭写通道,触发对端recv返回空值
    self.s.shutdown(socket.SHUT_WR)

现有服务端代码的逻辑优化

当前服务端的接收逻辑存在小隐患:哪怕后续触发了空接收的退出分支,代码依然会执行一次空字节的文件写入,建议调整逻辑把写操作挪到空值判断之后:

def download_file(self, file_name):
    downloading = True
    with open(file_name, "wb") as file:
        while downloading:
            l = self.client_socket.recv(64)
            if not l:
                print("downloaded")
                downloading = False
                break
            file.write(l)

工程化通用方案(适合长连接复用场景)

如果后续需要在单个TCP连接上传输多个文件,不适合每次传完就关闭写通道,可以在正式传输文件内容前,先把文件的总字节数用固定长度的字节格式(比如4字节/8字节大端整数)发给服务端。服务端收到元信息后,累计接收的字节数达到文件总长度时,就可以主动终止接收流程,不需要依赖连接关闭的信号。

内容的提问来源于stack exchange,提问作者jerev7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 14:36:04