高級FTP伺服器開發 一,作業要求 高級FTP伺服器開發 二,程式文件清單 Folder目錄:用戶文件目錄 bin目錄:程式啟動文件目錄 conf目錄:用戶配置文件目錄 core目錄:程式核心代碼目錄 log目錄:程式日誌文件目錄 三,程式流程簡圖 四,程式測試樣圖 創建賬戶 用戶登錄 基本操作 五 ...
高級FTP伺服器開發
一,作業要求
高級FTP伺服器開發
- 用戶加密認證(完成)
- 多用戶同時登陸(完成)
- 每個用戶有不同家目錄且只能訪問自己的家目錄(完成)
- 對用戶進行磁碟配額,不同用戶配額可不同(完成)
- 用戶登錄server後,可切換目錄(完成)
- 查看當前目錄下文件(完成)
- 上傳下載文件保持文件一致性(完成)
- 傳輸過程中實現進度條(完成)
- 可以創建或刪除目錄及文件(完成)
- 支持斷點續傳(未做)
二,程式文件清單
- Folder目錄:用戶文件目錄
- bin目錄:程式啟動文件目錄
- conf目錄:用戶配置文件目錄
- core目錄:程式核心代碼目錄
- log目錄:程式日誌文件目錄
三,程式流程簡圖
四,程式測試樣圖
- 創建賬戶
- 用戶登錄
- 基本操作
五,核心源碼清單
- 客戶端核心源碼
1 #!usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # auther:Mr.chen 4 # 描述: 5 6 import socket,os 7 import time,json 8 9 10 DIR = os.path.dirname(os.path.abspath(__file__)) 11 DIR = DIR.replace('core','Folder/') 12 HOST = 'localhost' 13 PORT = 8888 14 15 16 17 18 def ls_Method(s): 19 s.send("Begin!") 20 data = '' 21 while True: 22 buffer = s.recv(1024) 23 if buffer == 'Exit!': 24 break 25 if not buffer: 26 print ("伺服器傳輸錯誤!") 27 return 28 data += buffer 29 print (data) 30 31 32 def put_Method(s,action,filename): 33 if os.path.exists(DIR+filename) and os.path.isdir(DIR+filename) == False: 34 with open(DIR+filename,'r') as f: 35 data = f.read() 36 data_size = len(data) 37 s.send(str(data_size)) 38 if s.recv(1024) == 'OK!': 39 s.send(filename) 40 if s.recv(1024) == 'OK!': 41 print ("文件開始上傳,請稍後...") 42 with open(DIR+filename,'r') as f: 43 Num = None 44 data = '' 45 while True: 46 buffer = f.read(1024) 47 if not buffer: 48 s.send("Exit!") 49 break 50 s.send(buffer) 51 data += buffer 52 Num = download_Progress(data_size, len(data), Num) 53 if s.recv(1024) == 'OK!': 54 print ("上傳成功!磁碟配額剩餘{0}M".format(s.recv(1024))) 55 else: 56 print ("文件傳輸有損,請重新上傳!") 57 else: 58 print ("不能上傳!伺服器上已有重名的文件") 59 else: 60 print ("磁碟配額已滿,請清理磁碟空間!") 61 else: 62 s.send("False!") 63 print ("上傳失敗,沒有這個文件或目標是個文件夾") 64 65 66 def get_Method(s,action,filename): 67 s.send(filename) 68 print ("正在下載,請等待...") 69 data = '' 70 data_size = s.recv(1024) 71 if data_size == "Flase!": 72 print ("下載失敗!伺服器沒有找到或目標是個文件夾") 73 return 74 data_size = int(data_size) 75 Num = None 76 while True: 77 buffer = s.recv(1024) 78 if not buffer : 79 print ("文件損壞,請重新下載!") 80 break 81 data += buffer 82 Num = download_Progress(data_size,len(data),Num) 83 if data_size == len(data): 84 with open(DIR + filename, 'w') as f: 85 f.write(data) 86 print ("下載成功!") 87 break 88 89 90 def cd_Method(s,action,filename): 91 s.send(filename) 92 re = s.recv(1024) 93 if re == 'OK!': 94 print ("命令執行成功!") 95 elif re == 'NULL!': 96 print ("已到根目錄,不能繼續返回!") 97 else: 98 print ("目錄沒有找到!") 99 100 101 def mkdir_Method(s,action,filename): 102 s.send(filename) 103 if s.recv(1024) == 'OK!': 104 print ("目錄創建成功!") 105 else: 106 print ("已有同名目錄或文件!") 107 108 109 def rm_Method(s,action,filename): 110 s.send(filename) 111 re = s.recv(1024) 112 if re == "OK!": 113 print ("刪除成功!磁碟配額剩餘{0}M".format(s.recv(1024))) 114 elif re == "DIR!": 115 while True: 116 decide = raw_input("您選擇的目標是個文件夾,是否遞歸刪除(y/n):") 117 if decide == 'y': 118 s.send("OK!") 119 re = s.recv(1024) 120 if re == "OK!": 121 print ("刪除成功,磁碟配額剩餘{0}M".format(s.recv(1024))) 122 break 123 else: 124 print ("刪除失敗,原因未知!") 125 break 126 elif decide == 'n': 127 s.send("False!") 128 break 129 else: 130 print ("您的輸入有誤!") 131 else: 132 print ("沒有這個文件") 133 134 135 def download_Progress(size_total,size,Num): 136 num = size * 100 / size_total 137 if Num == None: 138 # print (str(num)+"%") 139 print "\r%d" % num, 140 time.sleep(0.01) 141 return num 142 elif num == Num: 143 return num 144 else: 145 print "\r%d" % num, 146 time.sleep(0.01) 147 return num 148 149 150 151 152 def MD5(password): 153 """ 154 加密函數 155 :param password: 156 :return: 157 """ 158 import hashlib 159 return hashlib.md5(password).hexdigest() 160 161 162 def File_transfer(s): 163 """ 164 用戶指令函數 165 :param s: 166 :return: 167 """ 168 169 while True: 170 command = raw_input("請輸入你想執行的命令>>") 171 if not command: 172 continue 173 if command.lower().strip() == 'help': 174 text = """ 175 請用'put'+'空格'+'文件名'的格式上傳文件 176 請用'get'+'空格'+'文件名'的格式下載文件 177 請用'cd'+'空格'+'目錄名'的格式進入家目錄下的子文件夾 178 請用'cd'+'空格'+'..'的格式返回上級目錄 179 請用'mkdir'+'空格'+'目錄名'的格式進入家目錄的文件夾 180 請用'rm'+'空格'+'文件名/目錄名'的格式刪除家目錄下的文件 181 輸入'ls'查看用戶伺服器家目錄 182 """ 183 print (text) 184 continue 185 try: 186 action,filename = command.strip().split() 187 action = action.lower() 188 except: 189 if command.lower().strip() == 'ls': 190 s.send('ls') 191 print ("正在查詢,請稍後...") 192 if s.recv(1024) == 'OK!': 193 ls_Method(s) 194 else: 195 print ("您的輸入有誤!輸入help查看幫助文檔") 196 continue 197 else: 198 s.send(action) 199 if s.recv(1024) == 'OK!': 200 eval(action+'_Method')(s,action,filename) 201 else: 202 print ("您的輸入有誤!輸入help查看幫助文檔") 203 204 205 def Login(s): 206 """ 207 用戶登錄 208 :param s: 209 :return: 210 """ 211 while True: 212 name = raw_input("請輸入你的登陸名:").strip() 213 password = raw_input("請輸入你的密碼:").strip() 214 if not name or not password: 215 print ("用戶名和密碼不能為空!") 216 continue 217 password = MD5(password) #密碼加密 218 data = [name,password] 219 s.send(json.dumps(data)) 220 if s.recv(1024) == 'OK!': 221 print ("用戶登陸成功!") 222 File_transfer(s) 223 else: 224 print ("用戶登陸失敗!") 225 226 227 def Main(): 228 """ 229 用戶登陸 230 :param s: 231 :param log: 232 :return: 233 """ 234 s = socket.socket() 235 try: 236 s.connect((HOST, PORT)) 237 s.send("Ready!") 238 239 data = s.recv(1024) #接收伺服器歡迎信息 240 if not data: 241 print ("伺服器異常!") 242 else: 243 print (data) 244 Login(s) 245 except Exception,e: 246 print "伺服器連接不上....", e 247 finally: 248 s.close() 249 250 251 if __name__ == "__main__": 252 Main()
- 伺服器端核心源碼
1 #!usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # auther:Mr.chen 4 # 描述: 5 6 import SocketServer 7 import os,time,sys,json 8 import admin_configure 9 DIR = os.path.dirname(os.path.abspath(__file__)) 10 DIR = DIR.replace('core','Folder/') 11 12 13 14 class Myserver(SocketServer.BaseRequestHandler): 15 16 def __init__(self,request,client_address,server): 17 SocketServer.BaseRequestHandler.__init__(self,request,client_address,server) 18 self.Name = '' #用戶名 19 self.Password = '' #用戶密碼 20 self.Quota = '' #用戶磁碟配額 21 self.Home_path = '' #用戶家目錄路徑 22 self.Current_path = '' #用戶當前路徑 23 self.DIR = [] #用戶進入過的子目錄列表 24 25 26 27 def ls_Method(self): 28 data = self.request.recv(1024) 29 if data == 'Begin!': 30 data = os.popen('ls'+' '+self.Current_path).read() 31 self.request.sendall(data) 32 time.sleep(0.5) 33 self.request.send("Exit!") 34 35 36 def put_Method(self): 37 data_size = self.request.recv(1024) 38 if data_size == 'False!': 39 return 40 if int(self.Quota) >= int(data_size): 41 self.request.send("OK!") 42 filename = self.request.recv(1024) 43 if os.path.exists(self.Current_path+filename) == False: 44 self.request.send("OK!") 45 data = '' 46 while True: 47 buffer = self.request.recv(1024) 48 if buffer == 'Exit!': 49 break 50 if not buffer: 51 break 52 data += buffer 53 self.Quota = str(int(self.Quota) - len(data)) 54 dict = admin_configure.config_read(self.Name) 55 dict['Quota'] = self.Quota 56 admin_configure.config_write(dict) 57 with open(self.Current_path+filename,'w') as f: 58 f.write(data) 59 if len(data) == int(data_size): 60 self.request.send("OK!") 61 time.sleep(0.25) 62 Quota = str(float(self.Quota)/1000000) 63 self.request.send(Quota) 64 else: 65 self.request.send("Flase!") 66 else: 67 self.request.send("False!") 68 else: 69 self.request.send("Flase!") 70 71 72 73 def get_Method(self): 74 filename = self.request.recv(1024) 75 if os.path.exists(self.Current_path+filename) and os.path.isdir(self.Current_path+filename) == False: 76 with open(self.Current_path+filename,'r') as f: 77 data = f.read() 78 self.request.send(str(len(data))) 79 time.sleep(0.5) 80 self.request.sendall(data) 81 else: 82 self.request.send("Flase!") 83 84 85 86 87 88 def cd_Method(self): 89 filename = self.request.recv(1024) 90 if filename == '..': 91 if len(self.DIR) == 0: 92 self.request.send("NULL!") 93 return 94 else: 95 # self.Current_path = self.Current_path.replace('/'+self.DIR[0]+'/','/') 96 list = self.Current_path.split('/') 97 del list[0] 98 del list[len(list) - 1] 99 del list[len(list) - 1] 100 str = '/' 101 for i in range(len(list)): 102 str = str + list[i] + '/' 103 self.Current_path = str 104 del self.DIR[0] 105 self.request.send("OK!") 106 elif os.path.isdir(self.Current_path+filename): 107 self.Current_path = self.Current_path + filename + '/' 108 self.DIR.insert(0,filename) 109 self.request.send("OK!") 110 else: 111 self.request.send("False!") 112 113 114 def mkdir_Method(self): 115 filename = self.request.recv(1024) 116 if os.path.exists(self.Current_path+filename): 117 self.request.send("False!") 118 else: 119 os.system("mkdir -p " + self.Current_path + filename) 120 if os.path.exists(self.Current_path + filename): 121 self.request.send("OK!") 122 else: 123 self.request.send("False!") 124 125 def rm_Method(self): 126 filename = self.request.recv(1024) 127 if os.path.exists(self.Current_path+filename): 128 if os.path.isdir(self.Current_path+filename): 129 self.request.send("DIR!") 130 if self.request.recv(1024) == "OK!": 131 data = os.popen('du'+' '+ '-sk' + ' ' + self.Current_path+filename).read() 132 data_size,file = data.strip().split() 133 os.system("rm -rf " + self.Current_path + filename) 134 self.Quota = str(int(self.Quota) + int(data_size)) 135 dict = admin_configure.config_read(self.Name) 136 dict['Quota'] = self.Quota 137 admin_configure.config_write(dict) 138 self.request.send("OK!") 139 time.sleep(0.25) 140 Quota = str(float(self.Quota) / 1000000) 141 self.request.send(Quota) 142 143 else: 144 return 145 else: 146 with open(self.Current_path+filename,'r') as f: 147 data = f.read() 148 os.system("rm -f " + self.Current_path + filename) 149 self.Quota = str(int(self.Quota) + len(data)) 150 dict = admin_configure.config_read(self.Name) 151 dict['Quota'] = self.Quota 152 admin_configure.config_write(dict) 153 self.request.send("OK!") 154 time.sleep(0.25) 155 Quota = str(float(self.Quota) / 1000000) 156 self.request.send(Quota) 157 else: 158 self.request.send("False!") 159 160 def Login_Method(self,data): 161 re = admin_configure.config_read(data[0]) 162 if re == None: 163 return False 164 else: 165 if re['Password'] == data[1]: 166 self.Name = re['Name'] 167 self.Password = re['Password'] 168 self.Quota = re['Quota'] 169 self.Home_path = re['Home_path'] 170 self.Current_path = re['Current_path'] 171 self.DIR = [] 172