最近研究了一下python在计算机之间断点传输的方法,主要是应对系统中断的发生。主要原理很简单,发送端每次发送文件时,首先接收来自于接收端的一个标志信息,告诉发送端已经接收到的字节数,然后从下一个字节开始发送即可。代码如下:
发送端:
import socket
import struct
import sys
import os
import time
if __name__ == '__main__':
file_name = sys.argv[1]
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((socket.gethostname(), 12345))
# 定义文件头信息;
file_head = struct.pack('128sl', os.path.basename(file_name).encode(),
os.stat(file_name).st_size)
sock.send(file_head)
received_size = int(sock.recv(2014).decode())
read_file = open(file_name, "rb")
read_file.seek(received_size)
while True:
# time.sleep(1)
file_data = read_file.read(10240)
if not file_data:
break
sock.send(file_data)
read_file.close()
sock.close()
添加了两行代码,注意read_file.seek(index)函数可以使下一次读取从index开始。
接收端代码:
import socket
import threading
import os
import struct
def sending_file(connection):
try:
file_info_size = struct.calcsize('128sl')
buf = connection.recv(file_info_size)
if buf:
file_name, file_size = struct.unpack('128sl', buf)
file_name = file_name.decode().strip('\00')
file_new_dir = os.path.join('receive')
# print(file_name, file_new_dir)
if not os.path.exists(file_new_dir):
os.makedirs(file_new_dir)
file_new_name = os.path.join(file_new_dir, file_name)
received_size = 0
if os.path.exists(file_new_name):
received_size = os.path.getsize(file_new_name)
connection.send(str(received_size).encode())
w_file = open(file_new_name, 'ab')
print("start receiving file:", file_name)
while not received_size == file_size:
r_data = connection.recv(10240)
received_size += len(r_data)
w_file.write(r_data)
w_file.close()
print("接收完成!\n")
connection.close()
except Exception as e:
print(e)
if __name__ == '__main__':
host = socket.gethostname()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, 12345))
sock.listen(5)
print("服务已启动---------------")
while True:
connection, address = sock.accept()
print("接收地址:", address)
thread = threading.Thread(target=sending_file, args=(connection,))
thread.start()
在接收数据之前,先查找本地已接收到的数据大小并反馈给发送端,然后才开始接收文件,从而实现断点续传。