要实现的FTP功能,
客户端通过get直接拉取服务器端的文件(ps:自己要提前知道服务器有那些文件)
实现流程:
ftp server
1. 读取文件名
2. 检测文件是否存在
3. 打开文件
4. 检测文件大小
5. 发送文件大小给客户端
6. 等客户端确认
7. 开始边读边发数据
8. 发送md5
分配有2个文件 一个做服务器端,一个客户端
服务器端接收命令给客户端返回文件
FTP_server.py
import hashlib
import socket ,os,time
server = socket.socket()
server.bind(('0.0.0.0',9999) )
server.listen()
while True:
conn, addr = server.accept()
print("new conn:",addr)
while True:
print("等待新指令")
data = conn.recv(1024)
if not data:
print("客户端已断开")
break
cmd,filename = data.decode().split()
print(filename)
if os.path.isfile(filename):
f = open(filename,"rb")
m = hashlib.md5()
file_size = os.stat(filename).st_size
conn.send( str(file_size).encode() ) #send file size
conn.recv(1024) #wait for ack
for line in f:
m.update(line)
conn.send(line)
print("file md5", m.hexdigest())
f.close()
conn.send(m.hexdigest().encode()) #send md5
print("send done")
server.close()
ftp_client.py
import socket
import hashlib
client = socket.socket()
client.connect(('localhost', 9999))
while True:
cmd = input(">>:").strip()
if len(cmd) == 0: continue
#判断通过get + 文件名来获取文件
if cmd.startswith("get"):
client.send(cmd.encode())
server_response = client.recv(1024)
print("servr response:", server_response)
client.send(b"ready to recv file")
file_total_size = int(server_response.decode())
received_size = 0
#把文件名发给客户端
filename = cmd.split()[1]
#定义保存接收的文件命名
f = open(filename + ".new", "wb")
m = hashlib.md5()
while received_size < file_total_size:
#多一层判断防止粘包
if file_total_size - received_size > 1024: # 要收不止一次
size = 1024
else: # 最后一次了,剩多少收多少
size = file_total_size - received_size
print("last receive:", size)
data = client.recv(size)
received_size += len(data)
m.update(data)
f.write(data)
# print(file_total_size,received_size)
else:
#保存接收文件的md5值
new_file_md5 = m.hexdigest()
print("file recv done", received_size, file_total_size)
f.close()
#远端文件的md5值
server_file_md5 = client.recv(1024)
print("server file md5:", server_file_md5)
print("client file md5:", new_file_md5)
client.close()
效果: