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

作者:Rookie_Max 时间:2022-11-11 19:53:04 

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

客户端可以查看服务器文件库中有什么文件。
客户端可以从文件库中下载文件到本地。
客户端可以上传一个本地文件到文件库。
使用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 ? 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", "\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文件服务器的操作方法网站的支持!

来源:https://blog.csdn.net/Rookie_Max/article/details/104351750

标签:python,ftp,服务器
0
投稿

猜你喜欢

  • Python 权限控制模块 Casbin

    2022-09-21 07:35:46
  • Golang使用Gin框架实现HTTP上传文件过程介绍

    2024-04-28 09:18:12
  • 在SQL触发器或存储过程中获取在程序登录的用户

    2024-01-29 09:30:40
  • MySQL8.0中binlog的深入讲解

    2024-01-16 23:22:02
  • JS简单模拟触发按钮点击功能的方法

    2024-04-22 13:02:52
  • python爬虫开发之PyQuery模块详细使用方法与实例全解

    2021-05-28 20:54:29
  • 对有自增长字段的表导入数据注意事项

    2024-01-22 17:54:51
  • asp如何修改WINNT的登录密码?

    2010-06-10 17:06:00
  • vue项目中使用Svg的方法

    2024-05-10 14:14:17
  • MySQL启动连接的命令以及与PHP程序连接的基本语法

    2023-11-14 22:27:26
  • 纯js实现遮罩层效果原理分析

    2024-02-24 01:32:14
  • 在Centos 5.5 上编译安装mysql 5.5.9

    2024-01-19 02:56:39
  • python+openCV利用摄像头实现人员活动检测

    2021-06-23 10:39:36
  • 基于PHP实现邮件实时通知功能

    2024-06-07 15:46:09
  • CSS的渲染效率:书写高效的CSS

    2008-11-13 16:55:00
  • 无组件上传图片到数据库中,asp解决方案

    2007-08-03 13:22:00
  • 贝聿铭写给年轻设计师的十点忠告

    2010-01-24 18:46:00
  • Python发送邮件封装实现过程详解

    2021-06-13 09:19:41
  • 如何不通过DSN访问SQL Server?

    2009-11-11 19:21:00
  • MySQL DDL执行方式Online DDL详解

    2024-01-25 00:00:56
  • asp之家 网络编程 m.aspxhome.com