脚本专栏 
首页 > 脚本专栏 > 浏览文章

Python模拟FTP文件服务器的操作方法

(编辑:jimmy 日期: 2025/1/16 浏览:3 次 )

分为服务端和客户端,要求可以有多个客户端同时操作。

客户端可以查看服务器文件库中有什么文件。
客户端可以从文件库中下载文件到本地。
客户端可以上传一个本地文件到文件库。
使用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, file), "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 ")
   msg = "D %s " % want
   s.send(msg.encode())
  elif data == "U": # 上传文件
   file = input("upload ")
   # 判断文件是否在客户端文件所在的目录且是文件
   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", "\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)
     # 收到约定的信息退出循环
     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文件服务器的操作方法,希望对大家有所帮助,也非常感谢大家对网站的支持!

上一篇:Python使用QQ邮箱发送邮件实例与QQ邮箱设置详解
下一篇:Python如何实现小程序 无限求和平均
一句话新闻
高通与谷歌联手!首款骁龙PC优化Chrome浏览器发布
高通和谷歌日前宣布,推出首次面向搭载骁龙的Windows PC的优化版Chrome浏览器。
在对骁龙X Elite参考设计的初步测试中,全新的Chrome浏览器在Speedometer 2.1基准测试中实现了显著的性能提升。
预计在2024年年中之前,搭载骁龙X Elite计算平台的PC将面世。该浏览器的提前问世,有助于骁龙PC问世就获得满血表现。
谷歌高级副总裁Hiroshi Lockheimer表示,此次与高通的合作将有助于确保Chrome用户在当前ARM兼容的PC上获得最佳的浏览体验。
友情链接:杰晶网络 DDR爱好者之家 南强小屋 黑松山资源网 白云城资源网 站点导航 SiteMap