诚意
诚意如你,当一诚的态度对待

导航

 

一:实现用户数据上传、下载功能以及MD5验证数据的一致性

法一:

 1 import socket
 2 import json
 3 import hashlib
 4 import os
 5 import struct
 6 
 7 
 8 server = socket.socket()
 9 
10 server.bind(('127.0.0.1',7000))
11 server.listen(5)
12 
13 while True:  #服务器服务需要处于打开状态
14     print("server is running ......")
15     conn,addr = server.accept()
16 
17     conn.send('欢迎使用文件上传与下载功能'.encode('utf8'))
18     while True:#服务器通讯持续连接状态
19         try:        #异常断开处理
20             cmd = conn.recv(1024).decode('utf8')    #接受客户端命令此时
21             if cmd == 'exit':   #正常退出
22                 break
23             if len(cmd) == 0:#若Linux系统异常断开,则退出连接
24                 break
25             cmd_list_dcit = json.loads(cmd) #反序列化取出字典内容
26             print(cmd_list_dcit)
27 
28             if cmd_list_dcit['command'] == 'put':
29                 conn.send('正在上传......'.encode('utf8'))
30                 #########################接受数据##################
31                 md5 = hashlib.md5()   #MD5摘要对象
32                 with open(cmd_list_dcit['file_name'],'wb') as f:
33                     data_len = 0
34                     data_now = ''
35                     while data_len < cmd_list_dcit['file_length']:  #写入数据
36                         data = conn.recv(1024)
37                         f.write(data)
38                         md5.update(data)        #加密数据
39                         data_len += len(data)
40                         print('已经上传%s'% data_len)
41                 ser_md5 = md5.hexdigest()   #获取加密数据
42                 conn.send('fa'.encode('utf8'))  #随意数据,防止黏包
43                 client_md5 = conn.recv(1024).decode('utf8')
44 
45                 if ser_md5 == client_md5:   #校验数据
46                     print("上传完成")
47                     conn.send('已经上传完成'.encode('utf8'))
48                     break
49                 else:
50                     print('上传失败')
51                     conn.send('已经上传失败'.encode('utf8'))
52 
53             elif  cmd_list_dcit['command'] == 'get':
54                 md5 = hashlib.md5()   #MD5摘要对象
55                 with open(cmd_list_dcit['filename'],'rb') as f:
56                     file_length = os.path.getsize(cmd_list_dcit['filename'])#文件长度
57                     res = struct.pack('i',file_length)
58                     conn.send(res)
59                     for line in f:      #发送要下载的数据
60                         print(type(line))
61                         conn.send(line)
62                         md5.update(line)
63                 server_md5 = md5.hexdigest()
64                 conn.recv(1024).decode('utf8')#此地随意接受数据,防止黏包
65                 conn.send(server_md5.encode('utf8'))
66         except Exception as e:
67             break
68     conn.close()
服务端
 1 import  socket
 2 import json
 3 import os
 4 import  hashlib
 5 import struct
 6 
 7 cli = socket.socket()
 8 cli.connect(('127.0.0.1',7000))
 9 data = cli.recv(1024).decode('utf8')
10 print(data)
11 class Func:
12 
13     def put(self,cmd_list):
14         file_length = os.path.getsize(cmd_list[-1])   #计算上传的文件的大小
15         cmd_list_dcit = {'command':cmd_list[0],
16                          'file_name':cmd_list[-1],
17                          'file_length':file_length
18                          }
19         cmd_command = json.dumps(cmd_list_dcit)   #把命令信息序列化成字符串
20         cli.send(cmd_command.encode('utf8'))  #发送命令信息
21         ready = cli.recv(1024)
22         print(ready.decode('utf8'))         #正在上传.....
23         ###########################上传文件################
24         md5 = hashlib.md5()#数据校验
25         with open(cmd_list_dcit['file_name'],'rb') as f:    #打开文件
26             for line in f:
27                 cli.send(line)
28                 md5.update(line)
29         while 1:
30             pass
31 
32         client_md5 = md5.hexdigest()
33 
34         cli.recv(1024).decode('utf8')
35         cli.send(client_md5.encode('utf8'))#发生MD5校验
36         fin = cli.recv(1024)  #服务端校验完后发回已经上传完成或者失败
37         print(fin.decode('utf8'))
38 
39     def get(self,cmd_list):
40         cmd_dcit = {'command':cmd_list[0],
41                     'filename':cmd_list[-1]
42                     }
43         cmd_dump = json.dumps(cmd_dcit)
44         cli.send(cmd_dump.encode('utf8'))
45         data_pack = cli.recv(4)
46         data_length = struct.unpack('i',data_pack)[0]  #取出要下载的数据的长度
47         data_now_length = 0
48 
49         md5 = hashlib.md5()         #MD5校验对象
50         with open(cmd_dcit['filename'],'wb') as f :  #下载数据
51             while data_now_length < data_length:
52                 data_y = cli.recv(1024)
53                 data_now_length += len(data_y)
54                 f.write(data_y)     #写入数据
55                 md5.update(data_y)  #数据加密
56                 print('下载了%s数据'% data_now_length)
57 
58         client_md5 = md5.hexdigest()  #获取数据密文
59         cli.send('h'.encode('utf8')) #此地放为了放置黏包
60         ser_md5 = cli.recv(1024).decode('utf8')
61         if ser_md5 == client_md5:
62             print("下载成功")
63         else:
64             print("下载失败")
65 
66 
67 obj = Func()
68 
69 cmd = input(">>>")  # put xxx
70 cmd_list = cmd.strip().split(' ')  # 识别命令
71 if os.path.exists(cmd_list[-1]):
72     if cmd_list[0] == 'put':
73         obj.put(cmd_list)  # 上传
74     elif cmd_list[0] == 'get':
75         obj.get(cmd_list)  #下载
76 else:
77     print("您输入的文件路径不存在")
客户端

 最终:加入并发

 1 import socket
 2 import json
 3 import hashlib
 4 import os
 5 import struct
 6 import socketserver
 7 
 8 class Myserver(socketserver.BaseRequestHandler):
 9     def handle(self):
10 
11 
12         while True:  # 服务器通讯持续连接状态
13             try:  # 异常断开处理
14                 print("server is running ......")
15 
16                 cmd = self.request.recv(1024).decode('utf8')  # 接受客户端命令此时
17                 if cmd == 'exit':  # 正常退出
18                     break
19                 if len(cmd) == 0:  # 若Linux系统异常断开,则退出连接
20                     break
21                 cmd_list_dcit = json.loads(cmd)  # 反序列化取出字典内容
22                 print(cmd_list_dcit)
23 
24                 if cmd_list_dcit['command'] == 'put':
25                     self.request.send('正在上传......'.encode('utf8'))
26                     #########################接受数据##################
27                     md5 = hashlib.md5()  # MD5摘要对象
28                     with open(cmd_list_dcit['file_name'], 'wb') as f:
29                         data_len = 0
30                         data_now = ''
31                         while data_len < cmd_list_dcit['file_length']:  # 写入数据
32                             data = self.request.recv(1024)
33                             f.write(data)
34                             md5.update(data)  # 加密数据
35                             data_len += len(data)
36                             print('已经上传%s' % data_len)
37 
38                     ser_md5 = md5.hexdigest()  # 获取加密数据
39                     self.request.send('fa'.encode('utf8'))  # 随意数据,防止黏包
40 
41                     client_md5 = self.request.recv(1024).decode('utf8')
42                     print(1)
43 
44                     if ser_md5 == client_md5:  # 校验数据
45                         print("上传完成")
46                         self.request.send('已经上传完成'.encode('utf8'))
47                         break
48                     else:
49                         print('上传失败')
50                         self.request.send('已经上传失败'.encode('utf8'))
51                         break
52 
53                 elif cmd_list_dcit['command'] == 'get':  #下载
54                     md5 = hashlib.md5()  # MD5摘要对象
55                     with open(cmd_list_dcit['filename'], 'rb') as f:
56                         file_length = os.path.getsize(cmd_list_dcit['filename'])  # 文件长度
57                         res = struct.pack('i', file_length)
58                         self.request.send(res)
59                         for line in f:  # 发送要下载的数据
60                             print(type(line))
61                             self.request.send(line)
62                             md5.update(line)
63                     server_md5 = md5.hexdigest()
64                     self.request.recv(1024).decode('utf8')  # 此地随意接受数据,防止黏包
65                     self.request.send(server_md5.encode('utf8'))
66             except Exception as e:
67                 break
68         self.request.close()
69 
70 server = socketserver.ThreadingTCPServer(('127.0.0.1',7000),Myserver)
71 
72 server.serve_forever()  #accept()
服务端
 1 import  socket
 2 import json
 3 import os
 4 import  hashlib
 5 import struct
 6 
 7 cli = socket.socket()
 8 cli.connect(('127.0.0.1',7000))
 9 
10 class Func:
11 
12     def put(self,cmd_list):
13         file_length = os.path.getsize(cmd_list[-1])   #计算上传的文件的大小
14         cmd_list_dcit = {'command':cmd_list[0],
15                          'file_name':cmd_list[-1],
16                          'file_length':file_length
17                          }
18         cmd_command = json.dumps(cmd_list_dcit)   #把命令信息序列化成字符串
19         cli.send(cmd_command.encode('utf8'))  #发送命令信息
20         ready = cli.recv(1024)
21         print(ready.decode('utf8'))         #正在上传.....
22         ###########################上传文件################
23         md5 = hashlib.md5()#数据校验
24         with open(cmd_list_dcit['file_name'],'rb') as f:    #打开文件
25             for line in f:
26                 cli.send(line)
27                 md5.update(line)
28 
29         client_md5 = md5.hexdigest()
30 
31         cli.recv(1024).decode('utf8')
32         cli.send(client_md5.encode('utf8'))#发生MD5校验
33         fin = cli.recv(1024)  #服务端校验完后发回已经上传完成或者失败
34         print(fin.decode('utf8'))
35         cli.close()
36 
37     def get(self,cmd_list):
38         cmd_dcit = {'command':cmd_list[0],
39                     'filename':cmd_list[-1]
40                     }
41         cmd_dump = json.dumps(cmd_dcit)
42         cli.send(cmd_dump.encode('utf8'))
43         data_pack = cli.recv(4)
44         data_length = struct.unpack('i',data_pack)[0]  #取出要下载的数据的长度
45         data_now_length = 0
46 
47         md5 = hashlib.md5()         #MD5校验对象
48         with open(cmd_dcit['filename'],'wb') as f :  #下载数据
49             while data_now_length < data_length:
50                 data_y = cli.recv(1024)
51                 data_now_length += len(data_y)
52                 f.write(data_y)     #写入数据
53                 md5.update(data_y)  #数据加密
54                 print('下载了%s数据'% data_now_length)
55 
56         client_md5 = md5.hexdigest()  #获取数据密文
57         cli.send('h'.encode('utf8')) #此地放为了放置黏包
58         ser_md5 = cli.recv(1024).decode('utf8')
59         if ser_md5 == client_md5:
60             print("下载成功")
61             cli.close()
62         else:
63             print("下载失败")
64             cli.close()
65 
66 
67 obj = Func()
68 
69 cmd = input(">>>")  # put xxx
70 cmd_list = cmd.strip().split(' ')  # 识别命令
71 if os.path.exists(cmd_list[-1]) and  cmd_list[0] != 'exit':
72     if cmd_list[0] == 'put':
73         obj.put(cmd_list)  # 上传
74 
75     elif cmd_list[0] == 'get':
76         obj.get(cmd_list)  #下载
77 elif cmd_list[0] == 'exit':
78     cli.send('exit'.encode('utf8'))
79 else:
80     print("您输入的文件路径不存在")
客户端

 

用法:在客户端运行输入get   xxx (下载)   或者  put   xxx(上传)

法二:仅上传

 1 import struct
 2 import socket
 3 import json
 4 import hashlib
 5 
 6 sock=socket.socket()
 7 sock.bind(('127.0.0.1',8800))
 8 sock.listen(5)
 9 
10 while 1:
11     print("server is working....")
12     conn,addr= sock.accept()
13     while 1:
14 
15         # 接收json的打包长度
16         file_info_length_pack=conn.recv(4)
17         file_info_length=struct.unpack("i",file_info_length_pack)[0]
18 
19         # 接收json字符串
20         file_info_json=conn.recv(file_info_length).decode("utf8")
21         file_info=json.loads(file_info_json)
22 
23         action=file_info.get("action")
24         filename=file_info.get("filename")
25         filesize=file_info.get("filesize")
26 
27         # 循环接收文件
28         md5=hashlib.md5()
29         with open("put/"+filename,"wb") as f:
30             recv_data_length=0
31             while recv_data_length<filesize:
32                 data=conn.recv(1024)
33                 recv_data_length+=len(data)
34                 f.write(data)
35                 # MD5摘要
36                 md5.update(data)
37                 print("文件总大小:%s,已成功接收%s"%(filesize,recv_data_length))
38 
39         print("接收成功!")
40         conn.send(b"OK")
41         print(md5.hexdigest())
42         md5_val=md5.hexdigest()
43         client_md5=conn.recv(1024).decode("utf8")
44         if md5_val==client_md5:
45              conn.send(b"203")
46         else:
47              conn.send(b"204")
服务端
 1 import socket
 2 import os
 3 import json
 4 import struct
 5 import hashlib
 6 
 7 sock=socket.socket()
 8 sock.connect(("127.0.0.1",8800))
 9 
10 
11 while 1 :
12     cmd=input("请输入命令:") # put 111.jpg
13 
14     action,filename=cmd.strip().split(" ")
15     filesize=os.path.getsize(filename)
16 
17     file_info={
18         "action": action,
19         "filename": filename,
20         "filesize": filesize,
21     }
22     file_info_json=json.dumps(file_info).encode("utf8")
23 
24     ret=struct.pack("i",len(file_info_json))
25     # 发送 file_info_json的打包长度
26     sock.send(ret)
27     # 发送 file_info_json字节串
28     sock.send(file_info_json)
29     # 发送 文件数据
30     md5=hashlib.md5()
31     with open(filename,"rb") as f:
32         for line in f:
33             sock.send(line)
34             md5.update(line)
35 
36     data=sock.recv(1024)
37     print(md5.hexdigest())
38     md5_val=md5.hexdigest()
39     sock.send(md5_val.encode("utf8"))
40     is_valid=sock.recv(1024).decode('utf8')
41     if is_valid=="203":
42         print("文件完整!")
43     else:
44         print("文件上传失败!")
客户端

 二:实现用户数据上传、一致性校验、进度条、断点续传功能

服务端

 1 import socketserver
 2 import json
 3 import os
 4 import hashlib
 5 import shutil
 6 
 7 #状态码
 8 CODE = {
 9     '1001':'从头开始上传文件',
10     '1002':'断点续传',
11     '1003':'上传成功,满足md5校验一致性',
12     '1004':'数据不一致,上传失败'
13 }
14 
15 
16 class Nbserver(socketserver.BaseRequestHandler):
17     def handle(self):
18         '''
19         self.request是客户端的socket对象
20         :return:
21         '''
22         # 1:接受命令
23         upload_cmd_bytes = self.request.recv(1024)
24 
25         cmd_dict = json.loads(upload_cmd_bytes.decode('utf-8'))
26         # 2:获取文件信息
27         file_md5 = cmd_dict['file_md5']
28         file_name = cmd_dict['file_name']
29 
30         file_md5_path = os.path.join(r'E:\python\老男孩\代码\网络编程\20180907\断电续传\home\lilz',file_md5)
31         file_name_path = os.path.join(r'E:\python\老男孩\代码\网络编程\20180907\断电续传\home\lilz',file_name)
32 
33         upload_file_size = cmd_dict['size']
34 
35         # 3:判断文件是否存在
36         exist = os.path.exists(file_md5_path)
37         if not exist:  #从头传
38             # 3.1通知客户端,可以开始上传了,已经准备好了
39             response = {'code': 1001}
40             self.request.sendall(json.dumps(response).encode('utf-8'))    #发对应状态码
41 
42             # 3.1.1接受客户端上传的数据
43             md5 = hashlib.md5()
44 
45             with open(file_md5_path,mode='ab')as f:
46                 recv_size = 0
47                 while recv_size < upload_file_size:
48                     data = self.request.recv(1024)
49                     f.write(data)#写到内存
50                     f.flush()   #刷到内存
51                     recv_size += len(data)
52                     md5.update(data)
53 
54                 MD5 = md5.hexdigest()
55 
56             # 3.1.3校验改名字
57             if file_md5 == MD5 :
58                 self.request.sendall(b'1003')        #数据一致
59 
60                 if not os.path.exists(file_name_path):#如果不存在此文件名
61                     shutil.move(file_md5_path,file_name_path)
62                 else:  #如果存在此文件名
63                     shutil.move(file_md5_path, file_name_path)#暂时未改
64 
65             else :
66                 self.request.sendall(b'1004')  #数据不一致
67         else:   #断点续传+大小
68             # 3.2通知客户端,可以开始断点上传
69             exist_size = os.stat(file_md5_path).st_size
70             response = {'code':1002,'size':exist_size}
71             self.request.sendall(json.dumps(response).encode('utf-8'))  # 发对应状态码
72 
73             with open(file_md5_path, mode='ab')as f:
74                 recv_size = exist_size
75                 while recv_size < upload_file_size:
76                     data = self.request.recv(1024)
77                     f.write(data)  # 写到内存
78                     f.flush()  # 刷到内存
79                     recv_size += len(data)
80             # 下面进行数据一致性校验
81             md5 = hashlib.md5()
82             with open(file_md5_path, mode='rb')as f1:
83                 for line in f1 :
84                     md5.update(line)
85             MD5 = md5.hexdigest()
86             if file_md5 == MD5:
87                 self.request.sendall(b'1003')  # 数据一致
88                 shutil.move(file_md5_path, file_name_path)
89             else:
90                 self.request.sendall(b'1004')  # 数据不一致
91 
92 
93 
94 if __name__ == '__main__':
95     server = socketserver.ThreadingTCPServer(('127.0.0.1',8005), Nbserver)
96     server.serve_forever()
server
 1 import socket
 2 import json
 3 import hashlib
 4 import os
 5 import time
 6 
 7 #状态码
 8 CODE = {
 9     '1001':'从头开始上传文件',
10     '1002':'断点续传'
11 }
12 
13 def file_md5(file_path):
14 
15     obj = open(file_path,'rb')
16     md5  = hashlib.md5()
17     for line in obj:
18         md5.update(line)
19     obj.close()
20 
21     return md5.hexdigest()
22 
23 
24 
25 sk = socket.socket()
26 sk.connect(('127.0.0.1',8005))
27 
28 
29 while True:
30     cmd = input('请输入要执行的命令')
31     #1.自定义协议{'cmd':upload,'file_path':'..'}
32     #需要MD5值,如果文件名重复怎么办呢,服务端用MD5当文件名
33     file_path = r'E:\python\老男孩\代码\网络编程\20180907\断电续传\client\1.jpg'
34     print(os.path.exists(file_path))
35     file_md5_val = file_md5(file_path)
36     file_name = os.path.basename(file_path)
37     file_size = os.stat(file_path).st_size
38 
39     cmd_dict = {'cmd':'upload','file_name':file_name,'size':file_size,'file_md5':file_md5_val}
40     upload_cmd_bytes = json.dumps(cmd_dict).encode('utf-8')
41     sk.sendall(upload_cmd_bytes)
42 
43     # 2:等待服务端的响应
44     response = json.loads(sk.recv(1024).decode('utf-8'))#得到状态码
45     if response['code'] == 1001:
46         #从头开始,文件迭代或者按下面方式想让它读多少就读多少
47         with open(file_path,mode='rb') as f :
48             send_size = 0
49             while  send_size < file_size:
50                 data = f.read(1024)
51                 sk.sendall(data)
52                 send_size += len(data)
53                 time.sleep(0.1)
54                 val = int(send_size / cmd_dict['size']*100)
55                 print('\r%s%s%%'% ('#'*val,val),end='')  #进度条
56         check = sk.recv(1024)
57         print(type(check))
58         if check == b'1003':
59             print("数据上传成功")
60 
61         else:
62             print("数据上传失败")
63 
64     else :#断点续传
65         exist_size = response['size']
66         with open(file_path, mode='rb') as f:
67             f.seek(exist_size)
68             send_size = exist_size
69             while send_size < file_size:
70                 data = f.read(1024)
71                 sk.sendall(data)
72                 send_size += len(data)
73                 time.sleep(0.1)
74                 val = int(send_size / cmd_dict['size'] * 100)
75                 print('\r%s%s%%' % ('#' * val, val), end='')  # 进度条
76         check = sk.recv(1024)
77         print(check)
78         if check == b'1003':
79             print("数据上传成功")
80 
81         else:
82             print("数据上传失败")
client

 

posted on 2018-09-05 20:35  诚意  阅读(119)  评论(0)    收藏  举报