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


Posted in Python onFebruary 18, 2020

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

客户端可以查看服务器文件库中有什么文件。
客户端可以从文件库中下载文件到本地。
客户端可以上传一个本地文件到文件库。
使用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文件服务器的操作方法,希望对大家有所帮助,也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
使用Python脚本来控制Windows Azure的简单教程
Apr 16 Python
在Python中处理字符串之isdecimal()方法的使用
May 20 Python
python动态网页批量爬取
Feb 14 Python
机器学习10大经典算法详解
Dec 07 Python
TensorFlow中权重的随机初始化的方法
Feb 11 Python
django传值给模板, 再用JS接收并进行操作的实例
May 28 Python
Django中反向生成models.py的实例讲解
May 30 Python
Python根据文件名批量转移图片的方法
Oct 21 Python
基于python历史天气采集的分析
Feb 14 Python
Python/Django后端使用PIL Image生成头像缩略图
Apr 30 Python
单身狗福利?Python爬取某婚恋网征婚数据
Jun 03 Python
解决pycharm下载库时出现Failed to install package的问题
Sep 04 Python
git查看、创建、删除、本地、远程分支方法详解
Feb 18 #Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
Feb 18 #Python
python实现根据给定坐标点生成多边形mask的例子
Feb 18 #Python
python有序查找算法 二分法实例解析
Feb 18 #Python
Python连接SQLite数据库并进行增册改查操作方法详解
Feb 18 #Python
Python 解析pymysql模块操作数据库的方法
Feb 18 #Python
Anaconda3+tensorflow2.0.0+PyCharm安装与环境搭建(图文)
Feb 18 #Python
You might like
PHP 创建文件(文件夹)以及目录操作代码
2010/03/04 PHP
PHP页面中文乱码分析
2013/10/29 PHP
php对包含html标签的字符串进行截取的函数分享
2014/06/19 PHP
PHP 实现的将图片转换为TXT
2015/10/21 PHP
PHP实现自动识别原编码并对字符串进行编码转换的方法
2016/07/13 PHP
JS+PHP实现用户输入数字后显示最大的值及所在位置
2017/06/19 PHP
tp5 sum某个字段相加得到总数的例子
2019/10/18 PHP
html数组字符串拼接的最快方法
2009/09/16 Javascript
锋利的jQuery 要点归纳(一) jQuery选择器
2010/03/21 Javascript
javascript suggest效果 自动完成实现代码分享
2012/02/17 Javascript
JS异常处理的一个想法(sofish)
2013/03/14 Javascript
jquery为页面增加快捷键示例
2014/01/31 Javascript
javascript的tab切换原理与效果实现方法
2015/01/10 Javascript
jQuery解析XML文件同时动态增加js文件的方法
2015/06/01 Javascript
整理Javascript数组学习笔记
2015/11/29 Javascript
Jquery Easyui验证组件ValidateBox使用详解(20)
2016/12/18 Javascript
jQuery中可见性过滤器简单用法示例
2018/03/31 jQuery
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
2018/05/15 NodeJs
js 实现在2d平面上画8的方法
2018/10/10 Javascript
Vue数据双向绑定原理实例解析
2020/05/15 Javascript
Python的Django框架中的URL配置与松耦合
2015/07/15 Python
Python实现将目录中TXT合并成一个大TXT文件的方法
2015/07/15 Python
pandas数据预处理之dataframe的groupby操作方法
2018/04/13 Python
python读取图片并修改格式与大小的方法
2018/07/24 Python
python整小时 整天时间戳获取算法示例
2019/02/20 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
python实现简单飞行棋
2020/02/06 Python
python_array[0][0]与array[0,0]的区别详解
2020/02/18 Python
用python 绘制茎叶图和复合饼图
2021/02/26 Python
html5 canvas fillRect坐标和大小的问题解决方法
2014/03/26 HTML / CSS
windeln官方海外旗舰店:德淘超人气母婴超市
2017/12/15 全球购物
社区工作者先进事迹
2014/01/18 职场文书
美丽家庭事迹材料
2014/05/03 职场文书
党员公开承诺书2015
2015/01/21 职场文书
Java数据开发辅助工具Docker与普通程序使用方法
2021/09/15 Java/Android
MySQL性能指标TPS+QPS+IOPS压测
2022/08/05 MySQL