You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python Socket客户端-服务器文件传输失败问题排查求助

Python Socket 客户端-服务器文件传输故障排查

我帮你梳理下代码里的几个关键问题,这就是目前无法传输文件的核心原因:

服务器端存在的问题

  • 缺少文件内容接收逻辑:你的服务器代码只实现了接收文件名的功能,当客户端发完文件名后,服务器就直接关闭了连接,完全没有准备接收后续的文件数据。
  • 无文件写入处理:内层循环只是在拼接完整的文件名,之后没有任何读取客户端发送的文件内容、并写入本地文件的代码逻辑。

客户端存在的问题

  • 重复建立连接且发送错误:客户端连续创建了两次Socket连接,完全没必要;第二次发送文件名时直接传入字符串'prova3.txt',没有用encode('utf-8')编码,运行时会抛出TypeError异常。
  • 未发送文件内容:客户端只告诉了服务器要传输的文件名,却没有读取本地文件的内容并发送给服务器,等于只完成了“告知文件名”的步骤,核心的文件数据根本没传。
  • 无意义的阻塞:第一次发送文件名后调用了s.shutdown(socket.SHUT_WR),随后尝试recv服务器响应,但你的服务器代码根本没有发送任何响应数据,这会导致客户端一直阻塞在recv步骤无法继续。

修正后的服务器代码

import socket, os, sys

def Main():
    # 获取本地IP(保留你原来的逻辑)
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    print(f"服务器IP: {IP}")
    
    host = IP
    port = 50001
    s = socket.socket()
    s.bind((host, port))
    print("服务器已启动,等待连接...")
    s.listen(1)
    
    while True:
        c, addr = s.accept()
        print(f"已连接客户端: {str(addr)}")
        
        # 第一步:接收文件名(以换行符作为结束标记,避免粘包)
        filename = ''
        while True:
            data = c.recv(1024).decode('utf-8')
            if '\n' in data:
                filename += data.split('\n')[0]
                break
            filename += data
        print(f"即将接收文件: {filename}")
        
        # 第二步:接收文件内容并写入本地
        with open(f"received_{filename}", 'wb') as f:
            while chunk := c.recv(1024):
                if not chunk:
                    break
                f.write(chunk)
        print(f"文件 {filename} 接收完成")
        c.close()

if __name__ == '__main__':
    Main()

修正后的客户端代码

import socket

def Main():
    host = '192.168.1.90'  # 替换为你的服务器实际IP
    port = 50001
    
    s = socket.socket()
    s.connect((host, port))
    
    filename = 'prova3.txt'
    # 第一步:发送文件名(加换行符作为结束标记)
    s.send(f"{filename}\n".encode('utf-8'))
    
    # 第二步:发送文件内容(分块发送,适配大文件)
    with open(filename, 'rb') as f:
        while chunk := f.read(1024):
            s.send(chunk)
    print(f"文件 {filename} 已成功发送")
    s.close()

if __name__ == '__main__':
    Main()

关键调整说明

  1. 解决粘包问题:给文件名添加换行符标记,让服务器能准确识别文件名的结束位置,避免和后续文件内容混淆。
  2. 完整传输流程:服务器新增了文件内容接收和本地写入逻辑,客户端补充了读取本地文件并分块发送的代码,完成“文件名告知-文件内容传输-本地写入”的完整流程。
  3. 简化连接逻辑:去掉客户端重复建立连接的冗余代码,一次连接完成所有传输动作。

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

火山引擎 最新活动