Python Socket多文件接收报错:ValueError无效二进制字面量求助
解决Python Socket文件接收时的ValueError问题
这个报错一眼就能看出核心问题:你的服务器端代码正尝试把一段HTML文本当成二进制数字字符串来转换整数,这显然和你预期的「文件名长度数据」完全不搭边。咱们一步步拆解原因和解决办法:
最可能的元凶:连错了服务器地址/端口
报错里的<DOCTYPE html...>是标准的HTTP响应头,这说明你的客户端socket意外连接到了一个Web服务器(比如80/8080端口的服务),而非你自己写的Socket文件服务器。对方返回的HTML被你的服务器当成了「文件名长度的二进制串」,自然会触发invalid literal for int() with base 2错误。
解决办法
立刻检查客户端代码里的s.connect(...)语句,确认IP地址和端口号完全匹配你的Socket服务器的监听地址。比如如果你的服务器是localhost:9999,就绝对不能写成localhost:80或者其他Web服务常用端口。
次要可能:TCP粘包/收发逻辑不严谨
如果确认连接地址没问题,那就要排查收发数据的逻辑了——TCP是流式协议,如果你没严格按照约定的格式收发,很可能导致数据串混,比如把后续的文件名甚至之前的残留数据当成了长度串。
客户端发送逻辑修正
你当前的代码有几个潜在坑:
- 直接发送字符串而不编码(Python3的
send只接受bytes类型) - 用
len(filename)算长度(如果文件名包含中文等多字节字符,字符串长度≠字节长度)
修正后的客户端发送代码:
import os import socket # 假设s是已经建立好的socket连接 path = "./your_directory" for files in os.listdir(path): filename = files # 先把文件名转成字节串,按字节长度计算(避免多字节字符坑) filename_bytes = filename.encode('utf-8') filename_len = len(filename_bytes) # 转成16位二进制字符串,再编码成字节发送 size_str = bin(filename_len)[2:].zfill(16) s.send(size_str.encode('utf-8')) # 发送文件名的字节串 s.send(filename_bytes) # 后续发送文件内容的逻辑...
服务器端接收逻辑修正
服务器端要严格先收固定16字节的长度串,再按长度收文件名:
import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('localhost', 9999)) server_socket.listen(5) while True: client_sock, addr = server_socket.accept() print(f"连接来自:{addr}") while True: # 先接收16字节的长度串 size_data = client_sock.recv(16) if not size_data: # 客户端断开连接 break try: size_str = size_data.decode('utf-8') filename_len = int(size_str, 2) except ValueError as e: print(f"无效的长度数据:{e},收到的原始数据:{size_data}") client_sock.close() break # 按约定长度接收文件名 filename_data = client_sock.recv(filename_len) if not filename_data: break filename = filename_data.decode('utf-8') print(f"收到文件名:{filename}") # 后续接收文件内容的逻辑... client_sock.close()
最后排查点:残留连接/未清空缓冲区
如果之前的测试中没有正确关闭socket连接,可能导致缓冲区残留旧数据,下次通信时干扰新数据。解决办法是每次通信完成后,客户端和服务器都要调用s.close()关闭连接,或者在每次接收前确保缓冲区已清空。
内容的提问来源于stack exchange,提问作者zatip
相关产品推荐
相关产品推荐

