国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

高級FTP服務器使用介紹

來源:懂視網 責編:小采 時間:2020-11-27 14:14:07
文檔

高級FTP服務器使用介紹

高級FTP服務器使用介紹:高級FTP服務器 1. 用戶加密認證 2. 多用戶同時登陸 3. 每個用戶有自己的家目錄且只能訪問自己的家目錄 4. 對用戶進行磁盤配額、不同用戶配額可不同 5. 用戶可以登陸server后,可切換目錄 6. 查看當前目錄下文件 7. 上傳下載文件,保證文件一致性 8. 傳輸
推薦度:
導讀高級FTP服務器使用介紹:高級FTP服務器 1. 用戶加密認證 2. 多用戶同時登陸 3. 每個用戶有自己的家目錄且只能訪問自己的家目錄 4. 對用戶進行磁盤配額、不同用戶配額可不同 5. 用戶可以登陸server后,可切換目錄 6. 查看當前目錄下文件 7. 上傳下載文件,保證文件一致性 8. 傳輸
高級FTP服務器
1. 用戶加密認證
2. 多用戶同時登陸
3. 每個用戶有自己的家目錄且只能訪問自己的家目錄
4. 對用戶進行磁盤配額、不同用戶配額可不同
5. 用戶可以登陸server后,可切換目錄
6. 查看當前目錄下文件
7. 上傳下載文件,保證文件一致性
8. 傳輸過程中現實進度條
9.支持斷點續傳
10.用戶操作日志

服務端 啟動參數 start
客戶端 啟動參數 -s localhost -P 9500

程序結構:
seniorFTP/#綜合目錄
|- - -ftp_client/#客戶端程序目錄
| |- - -__init__.py
| |- - -bin/#啟動目錄
| | |- - -__init__.py
| | |- - -client_ftp.py#客戶端視圖啟動
| |
| |- - -cfg/#配置目錄
| | |- - -__init__.py
| | |- - -config.py#配置文件
| |
| |- - -down/#下載文件目錄
| |
| |- - -putfile/#上傳文件目錄
| |
| |
| |- - -REDMAE
|- - -ftp_server/#服務端程序目錄
| |- - -__init__.py
| |- - -bin/#啟動目錄
| | |- - -__init__.py
| | |- - -start.py#服務端視圖啟動
| | |- - -user_reg.py#用戶注冊啟動
| |
| |- - -cfg/#配置目錄
| | |- - -__init__.py
| | |- - -config.py#配置文件
| | |- - -userpwd.cfg#用戶信息文件
| |
| |- - -core/#文件目錄
| | |- - -__init__.py
| | |- - -ftp_server.py#服務端主要邏輯 類
| | |- - -logs.py#日志主要邏輯 類
| | |- - -main.py#服務端啟動主程序
| |
| |- - -home/#用戶文件目錄
| | |- - -用戶/#個人目錄
| |
| |- - -log/#日志文件目錄
| |
| |- - -REDMAE
| |
|
|- - -REDMAE

先上流程圖:

詳細代碼如下:

|- - -ftp_client/#客戶端程序目錄
| |- - -__init__.py
| |- - -bin/#啟動目錄
| | |- - -__init__.py
| | |- - -client_ftp.py#客戶端視圖啟動

 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socket,os,json,getpass,hashlib 5 import os ,sys,optparse 6 7 STATUS_CODE={ 8 240:'格式出錯,格式:{"action":"get","filename":"filename","size":100}', 9 241:'指令錯誤', 10 242:'用戶密碼出錯', 11 243:'用戶或密碼出錯', 12 244:'用戶密碼通過校驗', 13 } 14 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 15 sys.path.append(BASE_DIR)#增加環境變量 16 from cfg import config 17 class FTPClient(object): 18 def __init__(self): 19 paresr=optparse.OptionParser() 20 paresr.add_option('-s','--server',dest='server',help='服務器地址') 21 paresr.add_option('-P','--port',type="int",dest='port',help='服務器端口') 22 paresr.add_option('-u','--username',dest='username',help='用戶名') 23 paresr.add_option('-p','--password',dest='password',help='密碼') 24 (self.options,self.args)=paresr.parse_args()#返回一個字典與列表的元組 25 self.verify_args(self.options,self.args)#判斷參數 26 self.ser_connect()#連接服務端 27 self.cmd_list=config.CMD_LIST 28 self.rat=0#文件斷點 29 30 #實例化一個連接端 31 def ser_connect(self): 32 self.c=socket.socket()#實例化一個連接端 33 self.c.connect((self.options.server,self.options.port))#進行連接 34 35 #判斷用戶與密碼是否成對出現 36 def verify_args(self,options,args): 37 if (options.username is None and options.password is None) or (options.username is not None and options.password is not None):#判斷用戶與密碼是否成對出現 38 pass##判斷用戶與密碼單個出現 39 else: 40 exit('出錯:請輸入用戶與密碼!')#退出 41 if options.server and options.port:#端口判斷 42 if options.port>0 and options.port<65535: 43 return True 44 else: 45 print('端口號:[%s]錯誤,端口范圍:0-65535'%options.port) 46 47 #登陸方法 48 def landing(self):#登陸方法 49 '''用戶驗證''' 50 if self.options.username is not None:#判斷用戶名已經輸入 51 #print(self.options.username,self.options.password) 52 return self.get_user_pwd(self.options.username,self.options.password)#返回結果 53 else: 54 print('用戶登陸'.center(60,'=')) 55 ret_count=0#驗證次數 56 while ret_count<5: 57 username=input('用戶名:').strip() 58 password=getpass.getpass('密碼:').strip() 59 if self.get_user_pwd(username,password): 60 return self.get_user_pwd(username,password)#調用遠程驗證用戶 返回結果 61 else: 62 ret_count+=1#次數加一 63 print('認證出錯次數[%s]'%ret_count) 64 else: 65 print('密碼出錯次數過多!') 66 exit() 67 68 #'''用戶名與密碼檢驗''' 69 def get_user_pwd(self,username,password): 70 '''用戶名與密碼檢驗''' 71 #發送 頭文件 72 data={ 73 'action':'auth', 74 'username':username, 75 'password':password 76 } 77 self.c.send(json.dumps(data).encode())#發送到服務器 78 response = self.get_response()#得到服務端的回復 79 if response.get('status_code') == 244: 80 print(STATUS_CODE[244]) 81 self.user = username#存下用戶名 82 self.user_dir=response.get('dir')#目錄 83 return True 84 else: 85 print(response.get("status_msg") ) 86 87 #服務器回復 88 def get_response(self):#服務器回復 89 '''服務器回復信息''' 90 data=self.c.recv(1024)#接收回復 91 data = json.loads(data.decode()) 92 return data 93 94 #指令幫助 95 def help(self):#指令幫助 96 attr=''' 97 help 指令幫助 98 ---------------------------------- 99 info 個人信息100 ----------------------------------101 ls 查看當前目錄(linux/windows)102 ----------------------------------103 pwd 查看當前路徑(linux/windows)104 ----------------------------------105 cd 目錄 切換目錄(linux/windows)106 ----------------------------------107 get filename 下載文件108 ----------------------------------109 put filename 上傳文件110 ----------------------------------111 --md5 使用md5 在get/put 后112 ----------------------------------113 mkdir name 創建目錄(linux/windows)114 ----------------------------------115 rmdir name 刪除目錄(linux/windows)116 ----------------------------------117 rm filename 刪除文件 (linux/windows)118 ----------------------------------119 exit 退出120 ----------------------------------121 '''.format()122 print(attr)123 124 ##交互125 def inter(self):#交互126 if self.landing():#通過用戶密碼認證127 print('指令界面'.center(60,'='))128 self.help()129 while True:130 cmd = input('[%s]-->指令>>>:'%self.user_dir).strip()131 if len(cmd)==0:continue#輸入空跳過132 if cmd=='exit':exit()#退出指令133 cmd_str=cmd.split()#用空格分割 取命令到列表134 #print(cmd_str)135 #print(len(cmd_str))136 if len(cmd_str)==1 and cmd_str[0] in self.cmd_list:#如果是單個命令 并且在命令列表中137 #if len(cmd_str)==1:#如果是單個命令 并且在命令列表中138 if cmd_str[0]==config.HELP:139 self.help()140 continue141 func=getattr(self,'cmd_compr')#調用此方法142 ret=func(cmd_str)143 if ret:144 continue145 else:146 pass147 elif len(cmd_str)>1:148 if hasattr(self,'cmd_%s'%cmd_str[0]):#判斷類中是否有此方法149 func=getattr(self,'cmd_%s'%cmd_str[0])#調用此方法150 func(cmd_str)#執行151 continue152 else:153 print('指令出錯!')154 self.help()#155 156 #'''是否要md5'''157 def cmd_md5_(self,cmd_list):158 '''是否要md5'''159 if '--md5' in cmd_list:160 return True161 162 #進度條163 def show_pr(self,total):#進度條164 received_size = 0 #發送的大小165 current_percent = 0 #166 while received_size < total:167 if int((received_size / total) * 100 ) > current_percent :168 print("#",end="",flush=True)#進度顯示169 current_percent = int((received_size / total) * 100 )170 new_size = yield #斷點跳轉 傳入的大小171 received_size += new_size172 173 #單個命令174 def cmd_compr(self,cmd_str,**kwargs):175 mag_dict={176 "action":"compr",177 'actionname':cmd_str[0]178 }179 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送數據180 cmd_res_attr=self.get_response()#得到服務器的回復181 if type(cmd_res_attr) is not int:#如果不int 類型182 if cmd_res_attr["status_code"] ==241:#命令不對183 print(cmd_res_attr['status_msg'])184 return185 if cmd_res_attr["status_code"] ==240:#命令不對186 print(cmd_res_attr['status_msg'])187 return188 size_l=0#收數據當前大小189 self.c.send('準備好接收了,可以發了'.encode('utf-8'))190 receive_data= ''.encode()191 while size_l< cmd_res_attr:192 data=self.c.recv(1024)#開始接收數據193 size_l+=len(data)#加上194 receive_data += data195 else:196 receive_data=receive_data.decode()197 try:198 receive_data=eval(receive_data)#轉為列表 或字典199 except Exception as e:200 pass201 if type(receive_data) is dict:#如果是字典202 for i in receive_data:203 print(i,receive_data[i])204 return 1205 if type(receive_data) is list:#如果是列表206 for i in receive_data:207 print(i)208 return 1209 print(receive_data)210 return 1211 212 #切換目錄213 def cmd_cd(self,cmd_list,**kwargs):214 '''切換目錄'''215 mag_dict={216 "action":"cd",217 'actionname':cmd_list[1]218 }219 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送數據220 msg_l=self.c.recv(1024)#接收數據 消息221 data=json.loads(msg_l.decode())222 if data["status_code"] ==251:#目錄不可切換223 print(data['status_msg'])224 return225 elif data["status_code"] ==252:#目錄可以換226 print(data['status_msg'])227 self.c.send(b'1')#發送到服務器,表示可以了228 data=self.c.recv(1024)229 print(data.decode())230 user_dir=data.decode()231 print(user_dir)232 self.user_dir=user_dir233 return234 elif data["status_code"] ==256:#目錄不存在235 print(data['status_msg'])236 return237 238 #刪除文件239 def cmd_rm(self,cmd_list,**kwargs):240 mag_dict={241 "action":"rm",242 'filename':cmd_list[1]243 }244 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送文件信息245 data=self.get_response()#得到服務器的回復246 if data["status_code"] ==245:#文件不存在247 print(data['status_msg'])248 #print('刪除前空間:',data['剩余空間'])249 return250 elif data["status_code"] ==254:#文件刪除完成251 print(data['status_msg'])252 print('刪除前空間:',data['剩余空間'])253 pass254 self.c.send(b'1')#發送到服務器,表示可以255 data=self.get_response()#得到服務器的回復256 if data["status_code"] ==255:#文件刪除完成257 print(data['status_msg'])258 print('刪除后空間:',data['剩余空間'])259 return260 261 #創建目錄262 def cmd_mkdir(self,cmd_list,**kwargs):263 mag_dict={264 "action":"mkdir",265 'filename':cmd_list[1]266 }267 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送文件信息268 data=self.get_response()#得到服務器的回復269 if data["status_code"] ==257:#目錄已經存在270 print(data['status_msg'])271 return272 elif data["status_code"] ==256:#目錄創建中273 print(data['目錄'])274 pass275 self.c.send(b'1')#發送到服務器,表示可以276 data=self.get_response()#得到服務器的回復277 if data["status_code"] ==258:#目錄創建中完成278 print(data['status_msg'])279 return280 pass281 282 #刪除目錄283 def cmd_rmdir(self,cmd_list,**kwargs):284 mag_dict={285 "action":"rmdir",286 'filename':cmd_list[1]287 }288 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送文件信息289 data=self.get_response()#得到服務器的回復290 if data["status_code"] ==256:#目錄不存在291 print(data['status_msg'])292 return293 elif data["status_code"] ==260:#目錄不為空294 print(data['status_msg'])295 print(data['目錄'])296 return297 elif data["status_code"] ==257:#目錄刪除中298 print(data['目錄'])299 pass300 self.c.send(b'1')#發送到服務器,表示可以301 data=self.get_response()#得到服務器的回復302 if data["status_code"] ==259:#目錄刪除完成303 print(data['status_msg'])304 return305 pass306 307 #上傳方法308 def cmd_put(self,cmd_list,**kwargs):#上傳方法309 if len(cmd_list) > 1:310 filename=cmd_list[1]#取文件名311 filename_dir=config.PUT_DIR+filename#拼接文件名路徑312 313 if os.path.isfile(filename_dir):#是否是一個文件314 filesize=os.stat(filename_dir).st_size#獲取文件大小315 #執行行為 名字,大小,是否316 mag_dict={317 "action":"put",318 'filename':filename,319 'size':filesize,320 'overridden':True,321 'md5':False322 }323 if self.cmd_md5_(cmd_list):#判斷是否進行MD5324 mag_dict['md5'] = True325 self.c.send(json.dumps(mag_dict).encode('utf-8'))#發送文件信息326 data=self.get_response()#得到服務器的回復327 if data["status_code"] ==250:#磁盤空間不足328 print(data['status_msg'])329 print(mag_dict['size'])330 return331 if data["status_code"] ==249:#磁盤空間足夠332 print(data['status_msg'])333 print('剩余空間',data['剩余空間'])334 self.c.send(b'1')#發送到服務器,表示可以上傳文件了335 data=self.get_response()#得到服務器的回復336 if data["status_code"] ==230:#斷點續傳337 print(data['status_msg'])338 print(data['文件大小'])339 self.rat=data['文件大小']#文件指針位置340 pass341 elif data["status_code"] ==231:#非斷點續傳342 print(data['status_msg'])343 self.rat=0#文件指針位置344 pass345 f=open(filename_dir,'rb')#打開文件346 f.seek(self.rat)#移動到位置347 print(mag_dict['md5'])348 self.c.send(b'1')#發送到服務器,表示可以上傳文件了349 if mag_dict['md5']==True:350 md5_obj = hashlib.md5()#定義MD5351 progress = self.show_pr(mag_dict['size']) #進度條 傳入文件大小352 progress.__next__()353 while self.rat<filesize:354 line=f.read(1024)355 self.c.send(line)356 try:357 progress.send(len(line))#傳入當前數據大小358 except StopIteration as e:359 print("100%")360 break361 md5_obj.update(line)#計算MD5362 363 else:364 print(filename,'發送完成!')365 f.close()366 md5_val = md5_obj.hexdigest()367 md5_from_server = self.get_response()#服務端的MD5368 if md5_from_server['status_code'] == 248:369 if md5_from_server['md5'] == md5_val:370 print("%s 文件一致性校驗成功!" % filename)371 return372 else:373 progress = self.show_pr(mag_dict['size']) #進度條 傳入文件大小374 progress.__next__()375 #for line in f:376 while self.rat<filesize:377 line=f.read(1024)378 self.c.send(line)379 try:380 progress.send(len(line))#傳入當前數據大小381 except StopIteration as e:382 print("100%")383 break384 #print(line)385 else:386 print(filename,'發送完成!')387 f.close()388 return389 else:390 print(filename,'文件不存在!')391 392 #下載方法393 def cmd_get(self,cmd_list,**kwargs):#下載方法394 #cmd_split= args[0].split()#指令解析395 # if len(cmd_list) == 1:396 # print("沒有輸入文件名.")397 # return398 #down_filename = cmd_list[1].split('/')[-1]#文件名399 down_filename=cmd_list[1]#取文件名400 file_path='%s/%s'%(config.GET_DIR,down_filename)#拼接文件路徑 用戶down目錄401 if os.path.isfile(file_path):#文件是否存402 filesize=os.stat(file_path).st_size#獲取文件大小403 name_down=True404 else:405 filesize=0406 name_down=False407 mag_dict={408 "action":"get",409 'filename':cmd_list[1],410 'name_down':name_down,411 'size':filesize412 }413 if self.cmd_md5_(cmd_list):#判斷是否進行MD5414 mag_dict['md5'] = True415 self.c.send(json.dumps(mag_dict).encode())#發送416 self.c.send(b'1')#發送到服務器,防粘包417 418 response = self.get_response()#服務器返回文件 的信息419 if response["status_code"] ==247:#如文件存在420 if name_down==True and response['file_size']==filesize:421 print('文件已經下載完成')422 self.c.send(b'2')423 return424 self.c.send(b'1')#發送到服務器,表示可以接收文件了425 #if name_down:426 received_size = filesize#當前接收的數據大小427 #else:428 #received_size = 0#當前接收的數據大小429 430 file_obj = open(file_path,"ab")#打開文件431 if self.cmd_md5_(cmd_list):432 md5_obj = hashlib.md5()433 progress = self.show_pr(response['file_size']) #進度條 傳入文件大小434 progress.__next__()435 while received_size< response['file_size']:436 if response['file_size'] - received_size>1024:#表示接收不止一次437 size=1024438 else:#最后一次439 size=response['file_size'] - received_size440 #print('最后一個大小',size)441 data= self.c.recv(size)#接收數據442 443 try:444 progress.send(len(data))#傳入當前數據大小445 except StopIteration as e:446 print("100%")447 received_size+=len(data)#接收數據大小累加448 file_obj.write(data)#寫入文件449 md5_obj.update(data)#進行MD5驗證450 else:451 print("下載完成".center(60,'-'))452 file_obj.close()453 md5_val = md5_obj.hexdigest()#獲取MD5454 #print(md5_val)455 md5_from_server = self.get_response()#服務端的MD5456 #print(md5_from_server['md5'])457 if md5_from_server['status_code'] == 248:458 if md5_from_server['md5'] == md5_val:459 print("%s 文件一致性校驗成功!" % down_filename)460 pass461 else:462 progress = self.show_pr(response['file_size']) #進度條 傳入文件大小463 progress.__next__()464 while received_size< response['file_size']:465 if response['file_size'] - received_size>1024:#表示接收不止一次466 size=1024467 else:#最后一次468 size=response['file_size'] - received_size469 #print('最后一個大小',size)470 data= self.c.recv(size)#接收數據471 472 try:473 progress.send(len(data))#傳入當前數據大小474 except StopIteration as e:475 print("100%")476 received_size+=len(data)#接收數據大小累加477 file_obj.write(data)#寫入文件478 pass479 480 else:481 print("下載完成".center(60,'-'))482 file_obj.close()483 pass484 self.c.send(b'1')#發送到服務器,表示可以接收文件了485 486 if __name__=='__main__':487 488 c=FTPClient()489 c.inter()
View Code
| |- - -cfg/#配置目錄
| | |- - -__init__.py
| | |- - -config.py#配置文件
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import os ,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 7 sys.path.append(BASE_DIR)#增加環境變量 8 #print(BASE_DIR) 9 10 PUT_DIR=BASE_DIR+'putfile\'#定義用戶上傳目錄文件路徑變量11 GET_DIR=BASE_DIR+'down\'#定義用戶下載目錄文件路徑變量12 HELP='help'13 CMD_LIST=['ls','pwd','info','help']
View Code
|- - -ftp_server/#服務端程序目錄
| |- - -__init__.py
| |- - -bin/#啟動目錄
| | |- - -__init__.py
| | |- - -start.py#服務端視圖啟動
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socket,os,json 5 import os ,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 7 sys.path.append(BASE_DIR)#增加環境變量 8 9 from core import main10 11 if __name__ == '__main__':12 13 main.ArvgHandler()
View Code
| | |- - -user_reg.py#用戶注冊啟動
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import configparser 6 import os ,sys 7 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 8 sys.path.append(BASE_DIR)#增加環境變量 9 from cfg import config10 #修改個信息 磁盤大小11 def set_info(name,pwd,size):12 config_info=configparser.ConfigParser()#讀數據13 config_info.read(config.AUTH_FILE)#讀文件 用戶名密碼14 #print(config_info.options(name))15 config_info[name]={}16 config_info.set(name,config.PWD,pwd)#密碼17 config_info.set(name,config.QUOTATION,size)#磁盤信息18 config_info.write(open(config.AUTH_FILE,'w'))#寫入文件19 file_path='%s/%s'%(config.USER_HOME,name)#拼接目錄路徑20 os.mkdir(file_path)#創建目錄21 print('創建完成'.center(60,'='))22 print('用戶名:[%s]
密碼:[%s]
磁盤空間:[%s]'%(name,pwd,size))23 24 if __name__ == '__main__':25 name=input('name:')26 pwd=input('pwd:')27 size=input('size:')28 set_info(name,pwd,size)
View Code
| | |- - -userpwd.cfg#用戶信息文件
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import os ,sys 6 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 7 sys.path.append(BASE_DIR)#增加環境變量 8 #HOME_PATH = os.path.join(BASE_DIR, "home") 9 10 11 12 #USER_DIR='%s\data\'%BASE_DIR#定義用戶數據目錄文件路徑變量13 #USER_DIR='%s/data'%BASE_DIR#定義用戶數據目錄文件路徑變量14 #USER_HOME='%s\home\'%BASE_DIR#定義用戶家目錄文件路徑變量15 USER_HOME='%s/home'%BASE_DIR#定義用戶家目錄文件路徑變量16 #LOG_DIR='%s\log\'%BASE_DIR#日志目錄17 USER_LOG='%s/log/user_log.log'%BASE_DIR#日志登陸文件18 USER_OPERT='%s/log/user_opert.log'%BASE_DIR#日志操作文件19 20 LOG_LEVEL='DEBUG'#日志級別21 22 AUTH_FILE='%s/cfg/userpwd.cfg'%BASE_DIR#用戶名密碼文件23 HOST='0.0.0.0'# IP24 PORT=9500#端口25 QUOTATION='Quotation'#磁盤空間26 PWD='PWD'#密碼
View Code
| |- - -core/#服務端主要文件目錄
| | |- - -__init__.py
| | |- - -ftp_server.py#服務端主要邏輯 類
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import socketserver,os,json,pickle,configparser,time 5 time_format='%Y%m%d%H%M%S'#定義時間格式 6 times=time.strftime(time_format)#定義時間 7 8 STATUS_CODE={ 9 230:'文件斷點繼傳', 10 231:'新文件', 11 240:'格式出錯,格式:{"action":"get","filename":"filename","size":100}', 12 241:'指令錯誤', 13 242:'用戶名或密碼為空', 14 243:'用戶或密碼出錯', 15 244:'用戶密碼通過校驗', 16 245:'文件不存在或不是文件', 17 246:'服務器上該文件不存在', 18 247:'準備發送文件,請接收', 19 248:'md5', 20 249:'準備接收文件,請上傳', 21 250:'磁盤空間不夠', 22 251:'當前已經為主目錄', 23 252:'目錄正在切換', 24 253:'正在查看路徑', 25 254:'準備刪除文件', 26 255:'刪除文件完成', 27 256:'目錄不存在', 28 257:'目錄已經存在', 29 258:'目錄創建完成', 30 259:'目錄刪除完成', 31 260:'目錄不是空的', 32 } 33 import os ,sys,hashlib 34 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 35 sys.path.append(BASE_DIR)#增加環境變量 36 from cfg import config 37 from core.logs import log_log 38 from core.logs import user_opert 39 40 41 class MyTCPHandler (socketserver.BaseRequestHandler):# 42 43 def setup(self): 44 print('監聽中。。') 45 #'''用戶名與密碼是否為空''' 46 def cmd_auth(self,*args,**kwargs):#用戶校驗 47 '''用戶名與密碼是否為空''' 48 data=args[0]#獲取 傳來的數據 49 if data.get('username') is None or data.get('password') is None:#如果用戶名或密碼為空 50 self.send_mge(242)#發送錯誤碼 51 name=data.get('username')#用戶名 52 pwd=data.get('password')#密碼 53 print(name,pwd) 54 user=self.authusername(name,pwd)#用戶名與密碼的校驗 獲名用戶名 55 if user is None:#用戶名不存在 56 self.send_mge(243) 57 else: 58 self.user=name#保存用戶名 59 self.home_dir='%s/%s'%(config.USER_HOME,self.user)#拼接 用戶home目錄路徑 用戶根目錄 60 self.user_home_dir=self.home_dir#當前所在目錄 61 # self.user_dir=self.user_home_dir.split('/')[-1]#當前所在目錄 相對 62 self.dir_join()#進行目錄拼接 63 self.send_mge(244,data={'dir':self.user_dir})#相對 目錄 64 65 #目錄拼接 66 def dir_join(self,*args,**kwargs): 67 self.user_dir=self.user_home_dir.split(self.home_dir)[-1]+'/'#當前所在目錄 相對 68 print(self.user_dir) 69 70 #'''用戶名與密碼的校驗'' 71 def authusername(self,name,pwd): 72 '''用戶名與密碼的校驗''' 73 config_info=configparser.ConfigParser()#讀數據 74 config_info.read(config.AUTH_FILE)#讀文件 用戶名密碼 75 if name in config_info.sections():#用戶名存 76 password=config_info[name]['PWD'] 77 if password==pwd:#密碼正確 78 print('通過校驗!') 79 config_info[name]['USERname']=name#名字的新字段 80 info_str='用戶[%s],成功登陸'%name 81 self.log_log.warning(info_str)#記錄日志 82 #log_log(info_str) 83 return config_info[name] 84 else: 85 info_str='用戶[%s],登陸錯誤'%name 86 #log_log(info_str) 87 self.log_log.warning(info_str)#記錄日志 88 return 0 89 90 #判斷文件 是否存在 91 def file_name(self,file_path): 92 if os.path.isfile(file_path):#文件是否存 93 return True 94 else: 95 return False 96 97 #判斷目錄是否存在 98 def file_dir(self,file_path): 99 if os.path.isdir(file_path):#目錄是否存100 return True101 else:102 return False103 104 #刪除文件105 def cmd_rm(self,*args,**kwargs):106 cmd_dict=args[0]#獲取字典107 action=cmd_dict["action"]108 filename =cmd_dict['filename']#文件名109 file_path='%s/%s'%(self.user_home_dir,filename)#拼接文件路徑110 if not self.file_name(file_path):111 self.send_mge(245)#文件不存在112 return113 else:114 user_size=self.disk_size()#獲取磁盤信息115 self.send_mge(254,data={'剩余空間':user_size})#準備刪除文件116 file_size=os.path.getsize(file_path)#獲取文件大小117 pass118 self.request.recv(1) #客戶端確認 防粘包119 os.remove(file_path)120 new_size=float((float(user_size)+float(file_size))/1024000)#空間大小增加121 self.set_info(str(new_size))#傳入新大小122 self.send_mge(255,data={'剩余空間':new_size})#刪除文件完成123 info_str=self.log_str('刪除文件')#生成日志信息124 self.user_opert.critical(info_str)#記錄日志125 return126 127 #創建目錄128 def cmd_mkdir(self,*args,**kwargs):129 cmd_dict=args[0]#獲取字典130 action=cmd_dict["action"]131 filename =cmd_dict['filename']#目錄名132 file_path='%s/%s'%(self.user_home_dir,filename)#拼接目錄路徑133 if self.file_dir(file_path):134 self.send_mge(257)#目錄已經 存在135 return136 else:137 self.send_mge(256,data={'目錄':'創建中...'})#目錄創建中138 self.request.recv(1) #客戶端確認 防粘包139 os.mkdir(file_path)#創建目錄140 self.send_mge(258)#目錄完成141 info_str=self.log_str('創建目錄')#生成日志信息142 self.user_opert.critical(info_str)#記錄日志143 return144 145 #刪除目錄146 def cmd_rmdir(self,*args,**kwargs):147 cmd_dict=args[0]#獲取字典148 action=cmd_dict["action"]149 filename =cmd_dict['filename']#目錄名150 file_path='%s/%s'%(self.user_home_dir,filename)#拼接目錄路徑151 if not self.file_dir(file_path):152 self.send_mge(256)#目錄不存在153 return154 elif os.listdir(file_path):155 self.send_mge(260,data={'目錄':'無法刪除'})#目錄不是空的156 return157 else:158 self.send_mge(257,data={'目錄':'刪除中...'})#目錄創建中159 self.request.recv(1) #客戶端確認 防粘包160 os.rmdir(file_path)#刪除目錄161 self.send_mge(259)#目錄刪除完成162 info_str=self.log_str('刪除目錄')#生成日志信息163 self.user_opert.critical(info_str)#記錄日志164 return165 166 #磁盤空間大小167 def disk_size(self):168 attr_list=self.user_info()#調用個人信息169 put_size=attr_list[1]#取得磁盤信息170 user_size=float(put_size)*1024000#字節171 return user_size172 173 #'''客戶端上傳文件 '''174 def cmd_put(self,*args,**kwargs):175 '''客戶端上傳文件 '''176 cmd_dict=args[0]#獲取字典177 filename =cmd_dict['filename']#文件名178 file_size= cmd_dict['size']#文件大小179 #user_home_dir='%s/%s'%(config.USER_HOME,self.user)#拼接 用戶home目錄路徑180 file_path='%s/%s'%(self.user_home_dir,filename)#拼接文件路徑181 user_size=self.disk_size()#取得磁盤信息182 if float(file_size)>float(user_size):#空間不足183 self.send_mge(250,data={'剩余空間':user_size})184 return185 self.send_mge(249,data={'剩余空間':user_size})#發送一個確認186 self.request.recv(1) #客戶端確認 防粘包187 if self.file_name(file_path):#判斷文件名是否存在,188 s_file_size=os.path.getsize(file_path)##獲取服務器上的文件大小189 if file_size>s_file_size:#如果服務器上的文件小于要上傳的文件進190 tmp_file_size=os.stat(file_path).st_size#計算臨時文件大小191 reversed_size=tmp_file_size#接收到數據大小192 self.send_mge(230,data={'文件大小':reversed_size})#發送臨時文件大小193 pass194 else:# file_size==s_file_size:#如果大小一樣195 file_path=file_path+'_'+times#命名新的文件 名196 reversed_size=0#接收到數據大小197 self.send_mge(231)#發送 不是斷點文件198 pass199 else:200 reversed_size=0#接收到數據大小201 self.send_mge(231)#發送 不是斷點文件202 pass203 204 f=open(file_path,'ab')205 self.request.recv(1) #客戶端確認 防粘包206 if cmd_dict['md5']:#是否有 md5207 md5_obj = hashlib.md5() # 進行MD5208 while reversed_size< int(file_size):#接收小于文件 大小209 if int(file_size) - reversed_size>1024:#表示接收不止一次210 size=1024211 else:#最后一次212 size=int(file_size) - reversed_size213 #print('最后一個大小',size)214 data= self.request.recv(size)#接收數據215 md5_obj.update(data)216 reversed_size+=len(data)#接收數據大小累加217 f.write(data)#寫入文件218 else:219 f.close()220 print('[%s]文件上傳完畢'.center(60,'-')%filename)221 md5_val = md5_obj.hexdigest()#得出MD5222 print(md5_val)223 self.send_mge(248,{'md5':md5_val})#發送md5給客戶端224 else:225 while reversed_size< int(file_size):#接收小于文件 大小226 if int(file_size) - reversed_size>1024:#表示接收不止一次227 size=1024228 else:#最后一次229 size=int(file_size) - reversed_size230 #print('最后一個大小',size)231 data= self.request.recv(size)#接收數據232 reversed_size+=len(data)#接收數據大小累加233 f.write(data)#寫入文件234 else:235 print('[%s]文件上傳完畢'%filename.center(60,'-'))236 f.close()237 new_size=float((float(user_size)-float(file_size))/1024000)#扣除空間大小238 self.set_info(str(new_size))#傳入新大小239 info_str=self.log_str('文件上傳')#生成日志信息240 self.user_opert.critical(info_str)#記錄日志241 return242 243 #用戶下載文件244 def cmd_get(self,*args,**kwargs):#用戶下載文件245 ''' 用戶下載文件'''246 data=args[0]247 print(data)248 if data.get('filename') is None:#判斷文件名不為空249 self.send_mge(245)250 return251 252 self.request.recv(1) #客戶端確認 防粘包253 file_path='%s/%s'%(self.user_home_dir,data.get('filename'))#拼接文件路徑 用戶文件路徑254 if os.path.isfile(file_path):#判斷文件是否存在255 file_obj=open(file_path,'rb')#打開文件句柄256 file_size=os.path.getsize(file_path)#獲取文件大小257 if data['name_down']:258 send_size=data['size']#已經發送數據大小259 #self.send_mge(230,data={'文件大小':file_size})#斷點續傳260 else:261 send_size=0262 #self.send_mge(231)#非斷點續傳263 #self.request.recv(1) #客戶端確認 防粘包264 file_obj.seek(send_size)#移動到265 self.send_mge(247,data={'file_size':file_size})#發送相關信息266 attr=self.request.recv(1024) #客戶端確認 防粘包267 if attr.decode()=='2':return #如果返回是268 if data.get('md5'):269 md5_obj = hashlib.md5()270 while send_size<file_size:271 line=file_obj.read(1024)272 #for line in file_obj:273 self.request.send(line)274 md5_obj.update(line)275 else:276 file_obj.close()277 md5_val = md5_obj.hexdigest()278 self.send_mge(248,{'md5':md5_val})279 print("發送完畢.")280 else:281 while send_size<file_size:282 line=file_obj.read(1024)283 #for line in file_obj:284 self.request.send(line)285 else:286 file_obj.close()287 print("發送完畢.")288 self.request.recv(1) #客戶端確認 防粘包289 info_str=self.log_str('下載文件')#生成日志信息290 #user_opert(info_str)#記錄日志291 self.user_opert.critical(info_str)#記錄日志292 return293 294 #切換目錄295 def cmd_cd(self,cmd_dict,*args,**kwargs):296 '''切換目錄'''297 cmd_attr=cmd_dict['actionname']#獲取命令298 if cmd_attr=='..' or cmd_attr=='../..':299 if (self.home_dir)==self.user_home_dir:300 self.send_mge(251)301 return302 elif cmd_attr=='../..':303 self.send_mge(252)#可以切換到上級目錄304 self.user_home_dir=self.home_dir#絕對目錄 = home305 self.user_dir='/'306 clinet_ack=self.request.recv(1024)#為了去粘包307 self.request.send(self.user_dir.encode())#返回相對目錄308 return309 else:310 self.send_mge(252)#可以切換到上級目錄311 print(self.user_home_dir)#絕對目錄312 print(os.path.dirname(self.user_home_dir))#父級目錄313 self.user_home_dir=os.path.dirname(self.user_home_dir)#父級目錄314 self.dir_join()#目錄拼接切換315 clinet_ack=self.request.recv(1024)#為了去粘包316 self.request.send(self.user_dir.encode())#返回相對目錄317 return318 319 elif os.path.isdir(self.user_home_dir+'/'+cmd_attr):#如果目錄存在320 self.send_mge(252)321 self.user_home_dir=self.user_home_dir+'/'+cmd_attr#目錄拼接322 self.dir_join()#相對目錄拼接切換323 clinet_ack=self.request.recv(1024)#為了去粘包324 print(clinet_ack.decode())325 self.request.send(self.user_dir.encode())326 return327 else:328 self.send_mge(256)#目錄不存在329 return330 331 #查看目錄路徑 CD332 def cmd_pwd(self,cmd_dict):333 self.request.send(str(len(self.user_dir.encode('utf-8'))).encode('utf-8'))#發送大小334 clinet_ack=self.request.recv(1024)#為了去粘包335 self.request.send(self.user_dir.encode())#發送相對路徑336 info_str=self.log_str('查看目錄路徑')#生成日志信息337 #logger.warning338 self.user_opert.critical(info_str)#記錄日志339 return340 341 #修改個信息 磁盤大小342 def set_info(self,new_size):343 config_info=configparser.ConfigParser()#讀數據344 config_info.read(config.AUTH_FILE)#讀文件 用戶名密碼345 print(config_info.options(self.user))346 config_info.set(self.user,config.QUOTATION,new_size)347 config_info.write(open(config.AUTH_FILE,'w'))348 349 #讀取個人信息350 def user_info(self):351 config_info=configparser.ConfigParser()#讀數據352 config_info.read(config.AUTH_FILE)#讀文件 用戶名密碼353 print(config_info.options(self.user))354 pwds=config_info[self.user][config.PWD]#密碼355 Quotation=config_info[self.user][config.QUOTATION]#磁盤配額 剩余356 user_info={}357 user_info['用戶名']=self.user358 user_info['密碼']=pwds359 user_info['剩余磁盤配額']=Quotation360 return user_info,Quotation361 362 #查看用戶信息363 def cmd_info(self,*args,**kwargs):364 attr=self.user_info()365 info_dict=attr[0]366 self.request.send(str(len(json.dumps(info_dict))).encode('utf-8'))#367 clinet_ack=self.request.recv(1024)#為了去粘包368 self.request.send(json.dumps(info_dict).encode('utf-8'))#發送指令369 info_str=self.log_str('查看用戶信息')#生成日志信息370 self.user_opert.critical(info_str)#記錄日志371 return372 373 #日志信息生成374 def log_str(self,msg,**kwargs):375 info_str='用戶[%s]進行了[%s]操作'%(self.user,msg)376 return info_str377 378 379 #目錄查看380 def cmd_ls(self,*args,**kwargs):381 data=os.listdir(self.user_home_dir)#查看目錄文件382 print(data)383 datas=json.dumps(data)#轉成json格式384 self.request.send(str(len(datas.encode('utf-8'))).encode('utf-8'))#發送大小385 clinet_ack=self.request.recv(1024)#為了去粘包386 self.request.send(datas.encode('utf-8'))#發送指令387 info_str=self.log_str('目錄查看')#生成日志信息388 self.user_opert.critical(info_str)#記錄日志389 return390 ##單個命令391 def cmd_compr(self,cmd_dict,**kwargs):392 attr=cmd_dict['actionname']#賦于變量393 if hasattr(self,'cmd_%s'%attr):#是否存在394 func=getattr(self,'cmd_%s'%attr)#調用395 func(cmd_dict)396 return397 else:398 print('沒有相關命令!')399 self.send_mge(241)400 return401 402 #'''發送信息碼給客戶端'''403 def send_mge(self,status_code,data=None):404 '''發送信息碼給客戶端'''405 mge={'status_code':status_code,'status_msg':STATUS_CODE[status_code]}#消息406 if data:#不為空407 mge.update(data)#提示碼進行更新408 print(mge)409 self.request.send(json.dumps(mge).encode())#發送給客戶端410 411 #重寫handle方法412 def handle(self):#重寫handle方法413 while True:414 #try:415 self.data=self.request.recv(1024).strip()#接收數據416 print('ip:{}'.format(self.client_address[0]))#連接的ip417 print(self.data)418 self.log_log=log_log()#登陸日志419 self.user_opert=user_opert()#操作日志420 if not self.data:421 print("[%s]客戶端斷開了!."%self.user)422 info_str='用戶[%s],退出'%self.user423 424 break425 cmd_dict=json.loads(self.data.decode())#接收 數據426 if cmd_dict.get('action') is not None:#判斷數據格式正確427 action=cmd_dict['action']#文件 頭428 if hasattr(self,'cmd_%s'%action):#是否存在429 func=getattr(self,'cmd_%s'%action)#調用430 func(cmd_dict)431 else:432 print('沒有相關命令!')433 self.send_mge(241)434 else:435 print('數據出錯!')436 self.send_mge(240)437 #except Exception as e:438 # print('客戶端斷開了!',e)439 # break
View Code
| | |- - -logs.py#日志主要邏輯 類
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 import os,logging,time 5 from cfg import config 6 LOG_LEVEL=config.LOG_LEVEL 7 8 9 def log_log():#登陸日志,傳入內容10 logger=logging.getLogger('用戶成功登陸日志')#設置日志模塊11 logger.setLevel(logging.DEBUG)12 fh=logging.FileHandler(config.USER_LOG,encoding='utf-8')#寫入文件13 fh.setLevel(config.LOG_LEVEL)#寫入信息的級別14 fh_format=logging.Formatter('%(asctime)s %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')#日志格式15 fh.setFormatter(fh_format)#關聯格式16 logger.addHandler(fh)#添加日志
輸出模式17 #logger.warning(info_str)18 return logger19 20 def user_opert():#用戶操作日志,傳入內容21 logger=logging.getLogger('用戶操作日志')#設置日志模塊22 logger.setLevel(logging.CRITICAL)23 fh=logging.FileHandler(config.USER_OPERT,encoding='utf-8')#寫入文件24 fh.setLevel(config.LOG_LEVEL)#寫入信息的級別25 fh_format=logging.Formatter('%(asctime)s %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')#日志格式26 fh.setFormatter(fh_format)#關聯格式27 logger.addHandler(fh)#添加日志輸出模式28 #logger.critical(info_str)29 return loggerView Code
| | |- - -main.py#服務端啟動主程序
 1 #!usr/bin/env python 2 #-*-coding:utf-8-*- 3 # Author calmyan 4 5 import socketserver,os,json,pickle 6 import os ,sys 7 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#獲取相對路徑轉為絕對路徑賦于變量 8 sys.path.append(BASE_DIR)#增加環境變量 9 from cfg import config10 11 12 from core.ftp_server import MyTCPHandler13 14 import optparse15 class ArvgHandler(object):16 def __init__(self):# 可 傳入系統參數17 self.paresr=optparse.OptionParser()#啟用模塊18 #self.paresr.add_option('-s','--host',dest='host',help='服務綁定地址')19 #self.paresr.add_option('-s','--port',dest='host',help='服務端口')20 (options,args)=self.paresr.parse_args()#返回一個字典與列表的元組21 22 self.verufy_args(options,args)#進行校驗23 def verufy_args(self,options,args):24 '''校驗與調用'''25 if hasattr(self,args[0]):#反射判斷參數26 func=getattr(self,args[0])#生成一個實例27 func()#開始調用28 else:29 self.paresr.print_help()#打印幫助文檔30 def start(self):31 print('服務啟動中....')32 s=socketserver.ThreadingTCPServer((config.HOST,config.PORT),MyTCPHandler)#實例化一個服務端對象33 s.serve_forever()#運行服務器34 print('服務關閉')
View Code


聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

高級FTP服務器使用介紹

高級FTP服務器使用介紹:高級FTP服務器 1. 用戶加密認證 2. 多用戶同時登陸 3. 每個用戶有自己的家目錄且只能訪問自己的家目錄 4. 對用戶進行磁盤配額、不同用戶配額可不同 5. 用戶可以登陸server后,可切換目錄 6. 查看當前目錄下文件 7. 上傳下載文件,保證文件一致性 8. 傳輸
推薦度:
標簽: 操作 使用 介紹
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 欧美日韩一二 | 亚洲欧洲中文字幕 | 国产日韩欧美 | 在线亚洲综合 | 亚洲欧美自拍一区 | 亚洲国产精品免费在线观看 | 欧美色图日韩色图 | 欧美在线亚洲 | 日韩欧美亚洲综合 | 国产亚洲欧美日韩综合另类 | 一级一级特黄女人精品毛片视频 | 国产精品亚洲色图 | 精品国产乱码一区二区三区麻豆 | 日韩欧美一区二区三区在线播放 | 欧美日韩一二 | 色另类| 免费看成人国产一区二区三区 | 在线视频观看国产 | 久久97久久| 九九精品视频一区在线 | 国产福利一区二区 | 欧美日韩在线精品一区二区三区 | 在线国产一区二区 | 欧美日韩亚洲一区二区三区 | 亚洲国产精品免费视频 | 黄毛片免费 | 日韩欧美一区二区三区视频 | 国产在线精品99一卡2卡 | 亚洲伦理中文字幕一区 | 久久2| 一级毛片免费观看久 | 免费看日产一区二区三区 | 亚洲国产精品嫩草影院久久 | 亚洲欧美日韩中文字幕在线 | 欧美激情一区二区三区视频 | 欧美人与禽交zozo | 国产手机视频在线观看 | 国产精品va一级二级三级 | 日韩欧美国产中文字幕 | 免费中文字幕 | 国产日韩欧美视频 |