1. 程式人生 > 程式設計 >Python模擬FTP檔案伺服器的操作方法

Python模擬FTP檔案伺服器的操作方法

分為服務端和客戶端,要求可以有多個客戶端同時操作。

客戶端可以檢視伺服器檔案庫中有什麼檔案。
客戶端可以從檔案庫中下載檔案到本地。
客戶端可以上傳一個本地檔案到檔案庫。
使用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檔案伺服器的操作方法,希望對大家有所幫助,也非常感謝大家對我們網站的支援!