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
相关产品推荐
相关产品推荐

