ftp服务端:
'''
简单的ftp服务
实现文件下载
文件校验
'''
import socket, os, hashlib
server = socket.socket()
server.bind(("localhost", 6666))
server.listen()
while True:
conn, addr = server.accept()
print("connect from:", addr)
while True:
data = conn.recv(1024).decode("utf-8", "ignore")
if not data:
print("客户端已断开")
break
cmd, filename = data.split()
if os.path.isfile(filename):
file_size = os.stat(filename).st_size
#发送文件大小
conn.send(str(file_size).encode())
#接收文件大小确认信息
size_ack = conn.recv(1024)
#开始发送文件
print(size_ack.decode("utf-8", "ignore"))
#创建md5加密实例
m = hashlib.md5()
#已二进制只读模式打开要发送的文件
f = open(filename, "rb")
send_size = 0
for line in f:
m.update(line)
#此处的数据发送可能和下一次发送的md5粘包
conn.send(line)
print("file md5:", m.hexdigest())
f.close()
conn.send(m.hexdigest().encode())
print("send done")
server.close()
ftp客户端:
#ftp 客户端
import socket, hashlib
client = socket.socket()
client.connect(("localhost", 6666))
while True:
data = input(">>:").strip()
if not data:continue
if data.startswith("get"):
filename = data.split()[1]
client.send(data.encode())
file_total_size = client.recv(1024).decode("utf-8", "ignore")
client.send("客户端已得知文件大小为{0}".format(file_total_size).encode())
f = open(filename+".new", "wb")
m = hashlib.md5()
recv_size = 0
recv_data = b""
while recv_size < int(file_total_size):
#此处为了防止MD5和最后一次发送的数据粘包
if int(file_total_size) - recv_size > 1024:
recv_data = client.recv(1024)
else:
#计算出最后一次剩余的数据大小,只接收此大小的数据
size = int(file_total_size) - recv_size
recv_data = client.recv(size)
f.write(recv_data)
m.update(recv_data)
recv_size += len(recv_data)
print("{0}/{1}".format(str(recv_size), file_total_size))
else:
print("数据已经接受完。")
print("开始验证md5")
print("client md5:", m.hexdigest())
f.close()
print("server md5:", client.recv(1024).decode("utf-8", "ignore"))
client.close()