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

文件传输程序循环无法终止求助:已接收文件但无法回到外层循环

文件传输程序内层循环无法终止的解决办法

问题原因

TCP属于流式传输协议,没有明确的“数据包边界”。你的代码中,客户端发送完所有文件数据后,服务器端的recv(4096)会一直阻塞等待新数据——因为它无法判断文件是否已经传输完毕,只有当连接被关闭时才会返回空数据触发break。而你的客户端发送完文件后并未关闭连接或发送结束信号,导致服务器内层循环一直卡在等待状态。

解决方案

方案1:传输前先发送文件大小

让客户端先把文件的总大小发给服务器,服务器根据已接收的字节数判断是否传输完成:

服务器端代码修改

# server side
while True:
    cmd = input("enter msg command :")
    client_socket.send(cmd.encode())
    if cmd.startswith("download"):
        filename = cmd.strip("download ")
        # 接收文件大小
        file_size = int(client_socket.recv(1024).decode())
        received_bytes = 0
        with open(filename, 'wb') as f:
            print("Downloading file...")
            while received_bytes < file_size:
                data = client_socket.recv(4096)
                if not data:
                    break
                f.write(data)
                received_bytes += len(data)
            print("Successfully downloaded")

客户端代码修改

# client side
import os

while True:
    command = s.recv(1024)
    command = command.decode()
    if command.startswith("download"):
        print("True\n")
        filename = command.strip("download ")
        # 获取并发送文件大小
        file_size = os.path.getsize(filename)
        s.send(str(file_size).encode())
        with open(filename,'rb') as f:
            print("file sending.....")
            while True:
                data = f.read(4096)
                if not data:
                    break
                s.sendall(data)
            print("file has sent")

方案2:发送结束标记

客户端发送完文件后,发送一个约定好的特殊标记,服务器收到该标记后终止循环:

服务器端代码修改

# server side
while True:
    cmd = input("enter msg command :")
    client_socket.send(cmd.encode())
    if cmd.startswith("download"):
        filename = cmd.strip("download ")
        with open(filename, 'wb') as f:
            print("Downloading file...")
            while True:
                data = client_socket.recv(4096)
                # 约定的结束标记,确保不会和文件内容冲突
                if data == b'__FILE_TRANSFER_DONE__':
                    break
                f.write(data)
            print("Successfully downloaded")

客户端代码修改

# client side
while True:
    command = s.recv(1024)
    command = command.decode()
    if command.startswith("download"):
        print("True\n")
        filename = command.strip("download ")
        with open(filename,'rb') as f:
            print("file sending.....")
            while True:
                data = f.read(4096)
                if not data:
                    # 发送结束标记
                    s.sendall(b'__FILE_TRANSFER_DONE__')
                    break
                s.sendall(data)
            print("file has sent")

注意事项

  • 方案1中,如果传输超大文件,建议用struct模块序列化文件大小(避免字符串编码的长度限制)。
  • 方案2中,要确保结束标记不会出现在正常文件内容中,否则会导致提前终止循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:33:46