Python模擬FTP文件服務器的操作方法
更新時間:2020年02月18日 15:41:30 作者:Rookie_Max
這篇文章主要介紹了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)
# 按通信協(xié)議格式組織數據
msg = "B " + ";".join(list)
# 發(fā)送到客戶端
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")
# 發(fā)送下載代碼,告知客戶端進入"D"
c.send(("D %s " % file).encode())
# 等待客戶端先進入"D"模式下的recv阻塞函數
time.sleep(0.1)
# 循環(huán)發(fā)送文件
while True:
data = f.read(1000)
if not data:
# 設置間隔,等待文件傳輸完整
time.sleep(0.1)
# 約定的信息讓客戶端退出接收循環(huán)
c.send(b"finished")
break
c.send(data)
f.close()
# 否則按協(xié)議格式發(fā)送錯誤代碼
else:
c.send(b"D fileerror ")
# 處理客戶端上傳文件請求
def upload(c, file):
# 創(chuàng)建文件
f = open("%s/%s" % (DIR, file), "wb")
# 循環(huán)接收文件
while True:
data = c.recv(1024)
# 收到約定的信息退出循環(huán)
if data == b"finished":
break
f.write(data)
f.close()
# 處理客戶端退出請求
def login_out(c):
# 按協(xié)議格式組織信息
msg = "O closed "
# 發(fā)給客戶端的recv_msg進程
c.send(msg.encode())
def deal(c):
# 發(fā)送代碼告知客戶端連接成功
c.send(b"K ")
while True:
# 循環(huán)接收客戶端請求,約定通信協(xié)議為"* ** ****"格式
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)
# 跳出循環(huán),結束子進程
break
# 主程序,父進程用于接收客戶端請求并循環(huán)創(chuàng)建子進程,子程序處理請求
def main():
# 創(chuàng)建tcp套接字
s = socket()
# 綁定服務器地址
s.bind(ADDR)
# 設置監(jiān)聽套接字
s.listen()
# 處理僵尸進程
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
while True:
# 連接客戶端
c, addr = s.accept()
# 創(chuàng)建子進程,用以處理客戶端請求,跳入deal函數
p = Process(target=deal, args=(c,))
# 子程序開始執(zhí)行
p.start()
if __name__ == '__main__':
main()
客戶端
# 導入相關模塊
from socket import *
import os, sys, time
# 綁定服務端IP地址
IP = "127.0.0.1"
# 綁定服務端端口
PORT = 8888
ADDR = (IP, PORT)
# 收到約定的信息退出循環(huán)
# 發(fā)送消息進程
def send_msg(s):
# 等待接收進程先運行到"K"分支
time.sleep(0.1)
while True:
try:
# 輸入指令
data = input(">>>")
except:
# 客戶端錯誤,向服務端發(fā)送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)
# 約定的信息讓客戶端退出接收循環(huán)
s.send(b"finished")
break
s.send(data)
f.close()
print("upload succussfully")
# 否則按協(xié)議格式顯示錯誤代碼
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", "\n>>>", 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)
# 收到約定的信息退出循環(huán)
if data == b"finished":
break
f.write(data)
f.close()
print("download successfully\n>>>", end="")
elif msg[0] == "O": # 收到來自發(fā)送消息進程發(fā)送到服務端的斷開請求
# 進程退出并打印提示
sys.exit("login out successfully")
# 主程序
def main():
# 創(chuàng)建tcp套接字
s = socket()
# 連接服務端
s.connect(ADDR)
# 創(chuàng)建多進程,子進程用于發(fā)送消息,父進程用于接收消息
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文件服務器的操作方法,希望對大家有所幫助,也非常感謝大家對腳本之家網站的支持!
相關文章
Python字符串編碼轉換 encode()和decode()方法詳細說明
這篇文章主要介紹了Python字符串編碼轉換 encode()和decode()方法詳細的說明,下面文章圍繞encode()和decode()方法的相相關資料展開內容,具有一定的價值,需要的朋友卡通參考一下2021-12-12
matplotlib.subplot()畫子圖并共享y坐標軸的方法
Matplotlib的可以把很多張圖畫到一個顯示界面,本文主要介紹matplotlib.subplot()畫子圖并共享y坐標軸的方法,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05
Python中的協(xié)程(Coroutine)操作模塊(greenlet、gevent)
這篇文章介紹了Python中的協(xié)程(Coroutine)操作模塊(greenlet、gevent),文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05
win10下opencv-python特定版本手動安裝與pip自動安裝教程
這篇文章主要介紹了win10下opencv-python特定版本手動安裝與pip自動安裝教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03

