Python模擬FTP檔案伺服器的操作方法
阿新 • • 發佈:2020-02-19
分為服務端和客戶端,要求可以有多個客戶端同時操作。
客戶端可以檢視伺服器檔案庫中有什麼檔案。
客戶端可以從檔案庫中下載檔案到本地。
客戶端可以上傳一個本地檔案到檔案庫。
使用print在客戶端列印命令輸入提示,引導操作
服務端
# 匯入相關模組 from socket import * from multiprocessing import Process import signal,os,time # 繫結IP地址 IP = "127.0.0.1" # 繫結埠 PORT = 8888 ADDR = (IP,PORT) # 繫結伺服器的指定目錄 DIR = "/home/max/ftp" # 處理檢視檔案請求 def browse(c): # 列表方式檢視檔案 list = os.listdir("%s" % DIR) # 按通訊協議格式組織資料 msg = "B " + ";".join(list) # 傳送到客戶端 c.send(msg.encode()) # 處理客戶端下載檔案請求 def download(c,file): # 判斷檔案是否存在且是否是檔案 if file in os.listdir(DIR) and os.path.isfile("%s/%s" % (DIR,file)): # 開啟檔案 f = open("%s/%s" % (DIR,file),"rb") # 傳送下載程式碼,告知客戶端進入"D" c.send(("D %s " % file).encode()) # 等待客戶端先進入"D"模式下的recv阻塞函式 time.sleep(0.1) # 迴圈傳送檔案 while True: data = f.read(1000) if not data: # 設定間隔,等待檔案傳輸完整 time.sleep(0.1) # 約定的資訊讓客戶端退出接收迴圈 c.send(b"finished") break c.send(data) f.close() # 否則按協議格式傳送錯誤程式碼 else: c.send(b"D fileerror ") # 處理客戶端上傳檔案請求 def upload(c,file): # 建立檔案 f = open("%s/%s" % (DIR,"wb") # 迴圈接收檔案 while True: data = c.recv(1024) # 收到約定的資訊退出迴圈 if data == b"finished": break f.write(data) f.close() # 處理客戶端退出請求 def login_out(c): # 按協議格式組織資訊 msg = "O closed " # 發給客戶端的recv_msg程序 c.send(msg.encode()) def deal(c): # 傳送程式碼告知客戶端連線成功 c.send(b"K ") while True: # 迴圈接收客戶端請求,約定通訊協議為"* ** ****"格式 msg = c.recv(1024) # 如果客戶端崩了,解除該子程序 if not msg: break # 解析請求 req = msg.decode().split(" ",2) # 處理檢視檔案請求,跳入browse函式 if req[0] == "B": browse(c) # 處理客戶端下載檔案請求,跳入download函式 elif req[0] == "D": download(c,req[1]) # 處理客戶端上傳檔案請求,跳入upload函式 elif req[0] == "U": upload(c,req[1]) # 處理客戶端退出請求,跳入login_out函式 elif req[0] == "O": login_out(c) # 跳出迴圈,結束子程序 break # 主程式,父程序用於接收客戶端請求並迴圈建立子程序,子程式處理請求 def main(): # 建立tcp套接字 s = socket() # 繫結伺服器地址 s.bind(ADDR) # 設定監聽套接字 s.listen() # 處理殭屍程序 signal.signal(signal.SIGCHLD,signal.SIG_IGN) while True: # 連線客戶端 c,addr = s.accept() # 建立子程序,用以處理客戶端請求,跳入deal函式 p = Process(target=deal,args=(c,)) # 子程式開始執行 p.start() if __name__ == '__main__': main()
客戶端
# 匯入相關模組 from socket import * import os,sys,time # 繫結服務端IP地址 IP = "127.0.0.1" # 繫結服務端埠 PORT = 8888 ADDR = (IP,PORT) # 收到約定的資訊退出迴圈 # 傳送訊息程序 def send_msg(s): # 等待接收程序先執行到"K"分支 time.sleep(0.1) while True: try: # 輸入指令 data = input(">>>") except: # 客戶端錯誤,向服務端傳送O data = "O" if data == "B": # 檢視目錄 msg = "B " s.send(msg.encode()) elif data == "D": # 下載檔案 # 輸入想要下載的檔案 want = input("download ? file:") msg = "D %s " % want s.send(msg.encode()) elif data == "U": # 上傳檔案 file = input("upload ? file:") # 判斷檔案是否在客戶端檔案所在的目錄且是檔案 if file in os.listdir(os.getcwd()) and os.path.isfile("%s/%s" % (os.getcwd(),file)): msg = "U %s " % file s.send(msg.encode()) f = open("%s" % file,"rb") # 等待服務端進入upload的recv阻塞函式 time.sleep(0.1) while True: data = f.read(1000) if not data: # 設定間隔,等待檔案傳輸完整 time.sleep(0.1) # 約定的資訊讓客戶端退出接收迴圈 s.send(b"finished") break s.send(data) f.close() print("upload succussfully") # 否則按協議格式顯示錯誤程式碼 else: print("file not exist\ninput BDUO to forward\n",end="") elif data == "O": # 斷開連線 msg = "O " s.send(msg.encode()) sys.exit() # 指令錯誤 else: print("input error") # 接收訊息程序 def recv_msg(s): while True: data = s.recv(1024) # 解析資料 msg = data.decode().split(" ",2) if msg[0] == "K": # 登入成功反饋 print( "login in successfully\ninput B to browse,D to download,U to upload,O to login out") elif msg[0] == "B": # 檢視目錄反饋 # 如果檔案庫不為空 if msg[2]: print("files:",msg[2],"\n>>>",end="") else: print("files: no files",end="") elif msg[0] == "D": # 服務端檔案不存在 if msg[1] == "fileerror": print("file not exist\ninput BDUO to forward\n>>>",end="") continue # 服務端檔案存在 else: f = open("%s" % msg[1],"wb") while True: data = s.recv(1024) # 收到約定的資訊退出迴圈 if data == b"finished": break f.write(data) f.close() print("download successfully\n>>>",end="") elif msg[0] == "O": # 收到來自發送訊息程序傳送到服務端的斷開請求 # 程序退出並列印提示 sys.exit("login out successfully") # 主程式 def main(): # 建立tcp套接字 s = socket() # 連線服務端 s.connect(ADDR) # 建立多程序,子程序用於傳送訊息,父程序用於接收訊息 pid = os.fork() if pid < 0: print("system error") # 子程序 elif pid == 0: send_msg(s) # 父程序 else: recv_msg(s) if __name__ == '__main__': main()
總結
以上所述是小編給大家介紹的Python_模擬FTP檔案伺服器的操作方法,希望對大家有所幫助,也非常感謝大家對我們網站的支援!