本文實例講述了Python實現基于多線程、多用戶的FTP服務器與客戶端功能。分享給大家供大家參考,具體如下:
項目介紹:
1. 用戶加密認證
2. 允許同時多用戶登錄
3. 每個用戶有自己的家目錄 ,且只能訪問自己的家目錄
4. 對用戶進行磁盤配額,每個用戶的可用空間不同
5. 允許用戶在ftp server上隨意切換目錄
6. 允許用戶查看當前目錄下文件
7. 允許上傳和下載文件,保證文件一致性
8. 文件傳輸過程中顯示進度條
實現的原理:
服務器端啟用端口監聽,并對每一連接啟用一個線程,對用戶登陸密碼采用SHA512進行加密并進行匹配,當用戶登陸成功后,實例化FTPS,并引導客戶端進入主命令模式,
然后實現FTP的上傳功能、下載功能、新建目錄、刪除文件或目錄、切換目錄等實例化操作,同時對相關上傳下載進行進度條顯示,服務器端顯示下載或上傳文件的大小等
客戶端與服務器協商建立連接后,進行用戶身份登陸,登陸成功接收服務器指令,轉入命令輸入窗口,同時對put 與 get命令進行判斷,實現特定的上傳與下載功能
核心代碼實現如下:
服務器端
main.py
#!/usr/bin/env python3.5# -*-coding:utf8-*-import os,sys,socket,pickleBASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))sys.path.append(BASEDIR)from conf import settingfrom core import file_handlerfrom core import db_handlerimport select,hashlibimport threadingdef login(username,password): """ FTP登陸驗證函數 :param username: :param password: :return: # testDict ={"username":"jjb","password":"123456","file_dir":"E:/python","file_size":500} # file = 'jjb.pkl' # fp = open(file,'wb') # pickle.dump(testDict,fp) # fp.close() f = open("jjb.pkl","rb") data = pickle.loads(f.read()) f.close() print(data) """ #實例化加密函數 hash = hashlib.sha512() db= db_handler.handler(setting.DATABASE,username) if os.path.isfile(db): f = open(db,"rb") data = pickle.loads(f.read()) f.close() if username == data["name"]: hash.update(bytes(data["password"],"utf8")) hash_pwd = hash.hexdigest() if hash_pwd == password: filedir = data["file_dir"] filesize = data["file_size"] return "True|%s|%s"%(filedir,filesize) else: return "False||" else: return "False||" else: return "False||"def process(conn,addr): flage = "False" # 接收客戶端連接請求信息 info = conn.recv(1000) if info.decode() == "connect": conn.send(bytes("login","utf8")) # 接收用戶及密碼信息 while flage =="False": user_check =conn.recv(8000) # 分割用戶名及密碼 username,password = str(user_check.decode()).split("|") # 調用登陸驗證函數 login_ack = login(username,password) flage,home,size = str(login_ack).split("|") # print(flage,home,size) # print("user_input:",username,"user_pass:",password) if flage =="True": # 登陸成功發送登陸確認信息給客戶端 conn.send(bytes("login_ack","utf8")) # 實例化FTPserver ftp = file_handler.FTPs(username,conn,home,size) # 登陸用戶,數據連接,工作目錄,磁盤配額 ftp.run() break else: # 登陸失敗,發送給客戶端重新驗證 conn.send(bytes("登陸失敗!","utf8"))def ftp_server(): ''' 啟動FTP服務器端,開啟線程監聽 :return: ''' server = socket.socket() server.bind((setting.IP_PORT["host"],setting.IP_PORT["port"])) server.listen(10) while True: r,w,e = select.select([server,], [], [], 1) for i,server in enumerate(r): conn,addr = server.accept() # 創建線程 t = threading.Thread(target=process, args=(conn, addr)) # 啟動線程 t.start() server.close()def run(): ftp_server()if __name__ =="__main__": run()
新聞熱點
疑難解答