问题描述
我正在尝试学习 python 套接字编程(网络),我有一个发送文件的函数,但我没有完全理解这个函数的每一行(无法理解)。有人可以逐行解释这是做什么的。我也不确定为什么它需要数据的长度来发送文件。另外,如果您能看到此功能的任何改进,谢谢。
def send_file(socket,filename):
with open(filename,"rb") as x:
data = x.read()
length_data = len(data)
try:
socket.sendall(length_data.to_bytes(20,'big'))
socket.sendall(data)
except Exception as error:
print("Error",error)
解决方法
这个协议被写成首先发送文件的大小,然后是它的数据。大小为 20 个八位字节(字节),序列化为“大端”,这意味着首先发送最高有效字节。假设你有一个 1M 的文件,
>>> val = 1000000
>>> val.to_bytes(20,'big')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fB@'
程序发送这 20 个字节,然后发送文件负载本身。接收器将读取 20 个八位字节,将其转换回文件大小,并确切知道要为文件接收多少个八位字节。 TCP 是一种流媒体协议。它不知道消息边界。协议需要某种方式来告诉对方有多少数据构成一条消息,这是一种常见的方式。
顺便说一句,这段代码有一个严重的问题,就是一次读取整个文件。假设它很大,这段代码会崩溃。
接收器看起来像下面这样。这是一个基本的。
import io
def recv_exact(skt,count):
buf = io.BytesIO()
while count:
data = skt.recv(count)
if not data:
return b"" # socket closed
buf.write(data)
count -= len(data)
return buf.getvalue()
def recv_file(skt):
data = recv_exact(skt,20)
if not data:
return b""
file_size = int.from_bytes(data,"big")
file_bytes = recv_exact(skt,file_size)
return file_bytes