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

Python Socket客户端连接完成与关闭方法及文件传输不完整异常的代码修复求助

问题分析与修复方案

你的问题核心在于服务端发送完所有文件后没有主动关闭连接,导致客户端的recv()一直处于阻塞等待状态,永远收不到代表连接结束的空字节,所以无法退出循环,也无法完成文件的最终写入(这就是最后几十行缺失的原因——文件流还没被正常关闭刷新)。另外客户端代码里有一些冗余的手动关闭操作,我们可以一起优化。

修复后的服务端代码(server.py)

import socket, json, random, threading, zipfile, requests, re
from bs4 import BeautifulSoup
from zipfile import *

def listen_user(user):
    try:
        for x in range(2018,2021,1):
            filename = "nvdcve-1.1-" + str(x) + ".json"
            print(f"Sending {filename}")
            with open(filename, 'rb') as file:
                # 分块发送文件,避免一次性读取大文件占用过多内存
                chunk = file.read(4096)
                while chunk:
                    user.sendall(chunk)
                    chunk = file.read(4096)
            print(f"File {filename} sent successfully")
    finally:
        # 发送完所有文件后,主动关闭连接,告诉客户端传输结束
        user.close()
        print("Closed connection with client")

def start_server():
    while True:
        user_socket, address = server.accept()
        print(f"User <{address[0]}> connected!")
        users.append(user_socket)
        listen_accepted_user = threading.Thread(
            target=listen_user,
            args=(user_socket,)
        )
        listen_accepted_user.start()

if __name__ == '__main__':
    users = []
    server = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )
    server.bind( ("127.0.0.1", 100) )
    server.listen(5)
    print('waiting for connection...')
    start_server()

修复后的客户端代码(client.py)

import socket, json, random
from threading import Thread

def start_client(client):
    savefilename = str(random.randint(1,10)) + 'new.json'
    print(f"Saving to file: {savefilename}")
    # 使用with语句会自动管理文件和socket的关闭,不需要手动调用close()
    with client, open(savefilename,'wb') as file:
        while True:
            recvfile = client.recv(4096)
            if not recvfile:
                print("Received end of data, exiting receive loop")
                break
            file.write(recvfile)
        print("File saved successfully, connection closed")

if __name__ == '__main__':
    client = socket.socket(
        socket.AF_INET,
        socket.SOCK_STREAM,
    )
    client.connect( ("127.0.0.1", 100) )
    start_client(client)

关键修复点说明

  • 服务端主动关闭连接:
    在listen_user函数的finally块中调用user.close(),确保无论是否发生异常,发送完所有文件后都会关闭客户端连接。这样客户端的recv()会收到空字节,触发退出循环的条件。同时优化了文件发送逻辑,分块读取发送,避免大文件一次性加载到内存中。
  • 客户端优化:
    移除了冗余的file.close()和client.close(),因为with语句会在代码块结束时自动调用这些资源的close()方法,更安全且简洁。现在客户端会在收到空字节后正常退出循环,完成文件写入,你会看到对应的输出信息。
  • 文件完整性保障:
    服务端分块发送+客户端分块写入,配合连接关闭的信号,确保所有数据都被写入文件(之前的缺失是因为客户端循环没结束,文件流没被正常刷新关闭)。

客户端正确关闭Socket连接的方法

  • 主动关闭:当你确定不需要再使用socket时,调用client.close(),但如果用了with语句,它会自动帮你处理。
  • 被动关闭:当服务端主动关闭连接时,客户端的recv()会返回空字节,这时候你就可以退出接收循环,随后socket会被自动或手动关闭。
  • 异常处理:建议在网络操作中加入try-except块,捕获ConnectionResetError等异常,避免程序崩溃,同时在异常处理中关闭socket。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 18:27:48