实现简单socket的ftp功能

时间:2020-10-29 09:20:17   收藏:0   阅读:14

1、服务器端

 1 import socket,os,hashlib
 2 server=socket.socket()
 3 server.bind(("localhost",9999))  # 绑定套接字
 4 
 5 server.listen()  # 服务器监听
 6 """
 7 FTP 流程
 8 1.读取文件名
 9 2.检测文件是否存在
10 3.打开文件
11 4.检测文件大小
12 5.发送文件大小给客户端
13 6.等客户端确认
14 7.开始边读边发数据
15 8.发送md5,双方做对比
16 """
17 while True:
18     conn,addr=server.accept()   # 接收一个套接口的连接
19 
20     while True:
21         data=conn.recv(1024) #接收
22         if not data:
23             print("客户端已断开")
24             break
25         cmd,filename= data.decode().split()
26         print(filename)
27         if os.path.isfile(filename):
28             with open(filename,"rb") as f:
29                 m=hashlib.md5()  # 创建一个md5
30                 file_size=os.stat(filename).st_size  # 利用os.stat().st_size 获取文件的大小
31                 conn.send(     str(file_size).encode()     ) # send file size
32                 client_ack=conn.recv(1024)  # wait for ack 防止连续发送导致的粘包
33                 for line in f:
34                     m.update(line)  # 每次接收一行,就更新md5
35                     conn.send(line)  # send line_data
36                 # print("file md5:",m.hexdigest())
37                 conn.send(m.hexdigest().encode())  # send md5_data
38         print("send done...")
39 
40 
41 server.close()

2、客户端

 1 import socket,hashlib
 2 
 3 # 调用进度条功能
 4 def progress(percent):
 5     if percent>=1:
 6         percent=1
 7     res=int(percent*50)*""
 8     print("\r[%-50s] %d%%" %(res,int(percent*100)) ,end="")
 9 
10 # 判断是否下载文件的单位
11 def k_m_g(size):
12     size=int(size)
13     if size<1024**2:
14         return size/1024,"K"
15     elif size<1024**3:
16         return size/(1024**2),"M"
17     else:
18         return size/(1024**3),"G"
19 
20 
21 client=socket.socket()
22 client.connect(("localhost",9999))
23 
24 done_size=1024   # 设置每次下载长度
25 
26 while True:
27     cmd = input(">>:").strip()
28     if len(cmd)==0:continue
29     if cmd.startswith("get"):
30         client.send(cmd.encode(utf-8))
31         server_response = client.recv(1024) # 接收文件大小
32         client.send("ready to recv file".encode(utf-8))  # 响应服务器请求,防止粘包
33         file_total_size = int(server_response.decode())   # 文件的总长度
34         num,msg=k_m_g(file_total_size)
35         print(fserver response:{round(num,2)}{msg} )
36         reversed_size=0
37         filename=cmd.split()[1]   # 获得get 后的第一个命令
38         with open(filename+.new,"wb") as f:
39             m=hashlib.md5()
40             recv=0
41             while reversed_size<file_total_size:
42                 if file_total_size-reversed_size>done_size:   # 判断是否是最后一次传输(防止粘包)
43                     size=done_size
44                 else:
45                     size=file_total_size-reversed_size
46                 data=client.recv(size)
47                 m.update(data) # 更新client端的md5 用于后续对比完整性
48                 reversed_size+=len(data)  # 传了多少长度的数据
49                 f.write(data)
50                 if recv < file_total_size:  # 小于文件长度就继续传,再调用进度条函数
51                     recv += len(data)
52                     percent = recv / file_total_size
53                     progress(percent)
54             else:
55                 client_file_md5=m.hexdigest()  # 传完后获取接收到数据的md5值
56                 print("\nfile recv done...")
57             server_file_md5=client.recv(1024)   # 获取服务器端传的md5
58             if server_file_md5.decode() != client_file_md5:
59                 print(MD5准确性校验未通过,数据不准确)
60 
61 client.close()

 执行效果:

技术图片

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!