文章出處

高級FTP服務器開發

一,作業要求

高級FTP服務器開發

  1. 用戶加密認證(完成)
  2. 多用戶同時登陸(完成)
  3. 每個用戶有不同家目錄且只能訪問自己的家目錄(完成)
  4. 對用戶進行磁盤配額,不同用戶配額可不同(完成)
  5. 用戶登錄server后,可切換目錄(完成)
  6. 查看當前目錄下文件(完成)
  7. 上傳下載文件保持文件一致性(完成)
  8. 傳輸過程中實現進度條(完成)
  9. 可以創建或刪除目錄及文件(完成)
  10. 支持斷點續傳(未做)

二,程序文件清單

  • 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                 return True
173             else:
174                 return False
175 
176 
177 
178 
179 
180 
181 
182     def handle(self):
183         conn = self.request
184         conn.recv(1024)
185         print ("收到來自{0}的客戶端連接...".format(self.client_address[0]))
186         conn.send("歡迎你!")
187         try:
188             while True:
189                 print ("正在等待客戶端發送驗證信息!")
190                 self.data = json.loads(conn.recv(1024))
191                 # if not self.data:
192                 #     break
193                 if not self.data or type(self.data) != list:
194                     conn.send("false!")
195                 else:
196                     re = self.Login_Method(self.data)
197                     if re == True:
198                         print ("客戶端認證成功!")
199                         conn.send("OK!")
200                         while True:
201                             print ("正在等待客戶端響應...")
202                             data = conn.recv(1024)
203                             # if not data:
204                             #     break
205                             if hasattr(self,data +'_Method'):
206                                 conn.send("OK!")
207                                 getattr(self,data +'_Method')()
208                             else:
209                                 conn.send("flase")
210 
211                     else:
212                         conn.send("flase!")
213         except Exception,e:
214             print "客戶端失去連接!",e
215 
216 def Main():
217     HOST = 'localhost'
218     PORT = 8888
219     s = SocketServer.ThreadingTCPServer((HOST, PORT), Myserver)
220     print ("正在等待客戶端連接...")
221     s.serve_forever()
222 
223 
224 
225 if __name__ == "__main__":
226     Main()

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()