Python09作业思路及源码:高级FTP服务器开发(仅供参考)

高级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 "
%d" % num,
140         time.sleep(0.01)
141         return num
142     elif num == Num:
143         return num
144     else:
145         print "
%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()
原文地址:https://www.cnblogs.com/chensiqiqi/p/6231486.html