一、Socketserver實作FTP,檔案上傳、下載
目錄結構

1、socketserver實作ftp檔案上傳下載,可以同時多用戶登錄、上傳、下載
效果圖:



二、上面只演示了下載,上傳也是一樣的,來不及演示了,上代碼
1、客戶端
1 import socket,hashlib,os,json,sys,time 2 3 4 5 class Ftpclient(object): 6 7 8 def __init__(self): 9 self.client = socket.socket() 10 11 def connect(self,ip,port): 12 self.client.connect((ip, port)) 13 14 15 def help(self): 16 msg=''' 17 ls 18 19 pwd 20 21 cd .. 22 23 get filename 24 25 put filename 26 27 ''' 28 print(msg) 29 30 31 def interactive(self): 32 """ 33 客戶端入口 34 :return: 35 """ 36 while True: 37 verify = self.authenticate() #服務器端認證 38 if verify: 39 while True: 40 cmd = input('輸入命令 >>').strip() 41 if len(cmd) == 0:continue 42 cmd_str = cmd.split()[0] 43 if hasattr(self,'cmd_%s' %cmd_str): 44 func = getattr(self,'cmd_%s' %cmd_str) 45 func(cmd) 46 else: 47 self.help() 48 49 50 def cmd_put(self,*args): 51 """ 52 上傳檔案 53 :param args: 54 :return: 55 """ 56 cmd_solit = args[0].split() 57 start_time = self.alltime() # 開始時間 58 if len(cmd_solit) > 1: 59 filename = cmd_solit[1] 60 if os.path.isfile(filename): 61 filesize = os.stat(filename).st_size 62 msg_dic = { 63 'filename':filename, 64 'size':filesize, 65 'overridden':True, 66 'action':cmd_solit[0] 67 } 68 69 self.client.send( json.dumps(msg_dic).encode('utf-8')) 70 server_respinse=self.client.recv(1024) #防止粘包,等服務器確認回傳 71 print('檔案開始上傳',server_respinse) 72 client_size = 0 73 f = open(filename,'rb') 74 for line in f: 75 client_size += self.client.send(line) 76 self.processBar(client_size,filesize) #進度條 77 else: 78 print('檔案傳輸完畢,大小為 %s'%client_size) 79 end_time = self.alltime() # 結束時間 80 print('本次上傳花費了%s 秒'%self.alltime(end_time,start_time)) 81 f.close() 82 else: 83 print(filename,'檔案不存在') 84 else: 85 print('輸入有誤!') 86 87 88 def cmd_get(self,*args): 89 """ 90 下載檔案 91 :param args: 92 :return: 93 """ 94 cmd_solit = args[0].split() 95 start_time = self.alltime() # 開始時間 96 filename = cmd_solit[1] 97 if len(cmd_solit) > 1: 98 msg_dic = { 99 'filename': filename, 100 'size': '', 101 'overridden': True, 102 'action': cmd_solit[0], 103 'file_exist':'' 104 } 105 self.client.send(json.dumps(msg_dic).encode('utf-8')) 106 self.data = https://www.cnblogs.com/km-thonder/p/self.client.recv(1024).strip() 107 108 cmd_dic = json.loads(self.data.decode('utf-8')) 109 print(cmd_dic) 110 if cmd_dic['file_exist']: 111 if os.path.isfile(filename): 112 f = open(filename + '.new', 'wb') 113 else: 114 f = open(filename, 'wb') 115 116 self.client.send(b'200 ok') #防止粘包,等服務器確認回傳 117 client_size = 0 118 filesize = cmd_dic['size'] 119 m = hashlib.md5() 120 while client_size < filesize: 121 data=https://www.cnblogs.com/km-thonder/p/self.client.recv(1024) 122 f.write(data) 123 client_size +=len(data) 124 m.update(data) 125 self.processBar(client_size, filesize) 126 else: 127 print('下載完畢') 128 end_time = self.alltime() # 結束時間 129 print('本次下載花費了%s 秒' % self.alltime(end_time, start_time)) 130 f.close() 131 new_file_md5 = m.hexdigest() 132 server_file_md5 = self.client.recv(1024) 133 print('MD5', server_file_md5,new_file_md5) 134 135 else: 136 print('下載的 %s檔案不存在'%filename) 137 138 else: 139 print('輸入有誤!') 140 141 142 def cmd_dir(self,*arge): 143 cmd_solit = arge[0].split() 144 if len(cmd_solit) > 0: 145 msg_dic = { 146 'action': cmd_solit[0] 147 } 148 self.client.send(json.dumps(msg_dic).encode()) 149 cmd_dir = self.client.recv(1024) 150 print(cmd_dir.decode()) 151 152 else: 153 print('輸入錯誤!') 154 155 156 157 def alltime(self,*args): 158 """ 159 計算上傳、下載時間 160 :param args: 161 :return: 162 """ 163 if args: 164 return round(args[0] - args[1]) 165 else: 166 return time.time() 167 168 169 def processBar(self,num, total): 170 """ 171 進度條 172 :param num:檔案總大小 173 :param total: 已存入檔案大小 174 :return: 175 """ 176 rate = num / total 177 rate_num = int(rate * 100) 178 if rate_num == 100: 179 r = '\r%s>%d%%\n' % ('=' * int(rate_num /3), rate_num,) 180 else: 181 r = '\r%s>%d%%' % ('=' * int(rate_num /3), rate_num,) 182 sys.stdout.write(r) 183 sys.stdout.flush 184 185 186 def authenticate(self): 187 """ 188 用戶加密認證 189 :return: 190 """ 191 username = input('輸入用戶名:>>') 192 password = input('輸入密碼:>>') 193 m = hashlib.md5() 194 if len(username) > 0 and len(password) >0: 195 username = ''.join(username.split()) 196 password = ''.join(password.split()) 197 m.update(username.encode('utf-8')) 198 m.update(password.encode('utf-8')) 199 200 m = { 201 'username':username, 202 'password':password, 203 'md5':m.hexdigest() 204 } 205 self.client.send(json.dumps(m).encode('utf-8')) 206 server_user_md5 = self.client.recv(1024).strip() 207 print(server_user_md5.decode()) 208 if server_user_md5.decode() == 'success': 209 print('登錄成功!') 210 return 'ok' 211 else: 212 print('用戶名密碼錯誤!') 213 else: 214 print('請輸入用戶名密碼') 215 216 217 218 f = Ftpclient() 219 f.connect('localhost',9999) 220 f.interactive()
2、服務器端
1 import socketserver,json,os,hashlib,sys,paramiko 2 3 import settings 4 5 class Mysocketserver(socketserver.BaseRequestHandler): 6 7 8 9 def put(self,*args): 10 ''' 11 接受客戶端上傳檔案 12 :return: 13 ''' 14 cmd_dic = args[0] 15 filename = cmd_dic['filename'] #獲取檔案名 16 filesize= cmd_dic['size'] #獲取檔案大小(位元組) 17 18 if os.path.isfile(filename): #判斷檔案是否存在 19 f = open(filename + '.new','wb') 20 else: 21 f = open(filename, 'wb') 22 23 self.request.send(b'200 ok') #防止粘包 24 print('%s 檔案開始上傳' % self.client_address[0]) 25 received_size = 0 26 while received_size < filesize: 27 data = https://www.cnblogs.com/km-thonder/p/self.request.recv(1024) 28 f.write(data) 29 received_size += len(data) 30 else: 31 print('檔案傳輸完畢',filename) 32 33 34 def get(self, *args): 35 ''' 36 客戶端下載檔案 37 :return: 38 ''' 39 msg_dic = { 40 'filename': '', 41 'size': '', 42 'overridden': True, 43 'action': '', 44 'file_exist': '' 45 } 46 47 cmd_solit = args[0] 48 filename = cmd_solit['filename'] 49 file_exist = os.path.isfile(filename) 50 msg_dic['file_exist'] = file_exist 51 print(file_exist) 52 if file_exist: 53 filesize = os.stat(filename).st_size 54 55 msg_dic['filename'] = filename 56 msg_dic['size'] = filesize 57 msg_dic['action'] = cmd_solit['action'] 58 59 self.request.send(json.dumps(msg_dic).encode('utf-8')) 60 server_respang = self.request.recv(1024) #防止粘包 61 print('開始傳輸',server_respang) 62 f = open(filename,'rb') 63 m = hashlib.md5() 64 for lien in f: 65 m.update(lien) 66 self.request.send(lien) 67 else: 68 print('傳輸完成') 69 f.close() 70 self.request.send(m.hexdigest().encode()) 71 else: 72 print('檔案不存在') 73 self.request.send(json.dumps(msg_dic).encode('utf-8')) 74 75 76 77 def client_authentication(self): 78 """ 79 客戶端認證 80 :return: 81 """ 82 self.client_user= self.request.recv(1024).strip() 83 client_xinxi = json.loads(self.client_user.decode('utf-8')) 84 try: 85 with open(settings.school_db_file + client_xinxi['username'],'rb') as f: 86 data =https://www.cnblogs.com/km-thonder/p/ json.load(f) 87 if data['md5'] == client_xinxi['md5']: #判斷用戶輸入是否和服務器端MD5是否一致 88 print('驗證成功!') 89 self.request.send('success'.encode()) 90 return 'success' 91 else: 92 self.request.send('error'.encode()) 93 except Exception as e: 94 print('沒有此用戶',e) 95 self.request.send('error'.encode()) 96 97 98 def dir(self,*args): 99 """ 100 查看目錄 101 :param args: 102 :return: 103 """ 104 cmd_split = args[0] 105 dd=cmd_split['action'] 106 result_os = os.popen(dd).read() 107 self.request.send(result_os.encode()) 108 109 110 111 def handle(self): 112 """ 113 服務器端入口 114 :return: 115 """ 116 while True: 117 try: 118 success = self.client_authentication() 119 if success: 120 self.data=https://www.cnblogs.com/km-thonder/p/self.request.recv(1024).strip() 121 cmd_dic = json.loads(self.data.decode('utf-8')) 122 action = cmd_dic['action'] 123 if hasattr(self,action): 124 func = getattr(self,action) 125 func(cmd_dic) 126 except ConnectionResetError as e: 127 print('連接斷開',self.client_address[0]) 128 break 129 130 131 132 if __name__ == '__main__': 133 134 HOST,PORT='localhost',9999 135 server=socketserver.ThreadingTCPServer((HOST,PORT),Mysocketserver) 136 server.serve_forever()
settings.py 檔案
1 import os 2 3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 5 DB_FILE = os.path.join(BASE_DIR, "data\\") 6 7 school_db_file = os.path.join(DB_FILE) 8 print(school_db_file)
data里兩個做測驗的檔案,
1 alex 檔案內容: 2 {"username": "alex", "password": "123456", "md5": "94e4ccf5e2749b0bfe0428603738c0f9"}
kml123456檔案內容: {"username": "kml123456", "password": "123456","md5": "a791650e70ce08896e3dafbaa7598c26"}
到這里差不多就沒了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/163626.html
標籤:Python
上一篇:Python線性資料結構
