python_ftp

python_ftp,第1张

概述FTP文件服务器需求分析:(1)分为服务器和客户端,要求可以有多个客户端同时 *** 作(2)客户端可以查看服务器文件库中有什么文件(3)客户端可以从文件库中下载文件到本地(4)客户端可以上场一个本地文件到文件库(5)使用print在客户端打印命令输入提示,引导 *** 作技术点分析:C/S模式并发 FTP 文件服务器

需求分析:
(1)分为服务器和客户端,要求可以有多个客户端同时 *** 作
(2)客户端可以查看服务器文件库中有什么文件
(3)客户端可以从文件库中下载文件到本地
(4)客户端可以上场一个本地文件到文件库
(5)使用print 在客户端打印命令输入提示,引导 *** 作

技术点分析:
C / S 模式
并发模型 : 多线程
网络: TCP网络
文件传输: 边读边发 边收边写

功能模块划分和封装 : 函数 + 类

         搭建整体结构框架          查看文件目录            下载文件         上传文件

通信协议:
请求类型 数据参量
获取文件列表 List
下载文件 RETR filename
上传文件 STOR filename
退出 EXIT

“”"
-----------------FTP文件服务 服务端
“”"

from socket import *from threading import Threadimport os, time# 全局变量HOST = '0.0.0.0'PORT = 8888ADDR = (HOST, PORT)  # 服务器地址# 文件库FTP = "/root/"# 处理客户端请求class FTPServer(Thread):    def __init__(self, connfd):        super().__init__()        self.connfd = connfd    def do_List(self):        # 判断文件库是否为空        file_List = os.Listdir(FTP)        if not file_List:            self.connfd.send(b'FAIL')  # 列表为空            return        else:            self.connfd.send(b'OK')            time.sleep(0.1)            data = "\n".join(file_List)            self.connfd.send(data.encode())    # 处理下载    def do_get(self, filename):        try:            f = open(FTP + filename, 'rb')        except:            # 文件不存在报异常            self.connfd.send(b"FAIL")            return        else:            # 文件打开成功            self.connfd.send(b"OK")            time.sleep(0.1)            # 发送文件            while True:                data = f.read(1024)                if not data:                    time.sleep(0.1)                    self.connfd.send(b"##")  # 文件发送完毕                    break                self.connfd.send(data)            f.close()    # 处理上传    def do_put(self, filename):        if os.path.exists(FTP + filename):            self.connfd.send(b"FAIL")            return        else:            self.connfd.send(b"OK")            # 接收文件            f = open(FTP + filename, 'wb')            while True:                data = self.connfd.recv(1024)                if data == b"##":                    break                f.write(data)            f.close()    # 作为一个线程内容处理某一个客户端的请求    def run(self):        # 总分模式        while True:            # 某个客户端所有的请求            data = self.connfd.recv(1024).decode()            print("Request:", data)  # 调试            # 更具不同的请求做不同处理            if not data or data == 'EXIT':                self.connfd.close()                return            elif data == 'List':                self.do_List()            elif data[:4] == 'RETR':                filename = data.split(' ')[-1]                self.do_get(filename)            elif data[:4] == 'STOR':                filename = data.split(' ')[-1]                self.do_put(filename)def main():    # tcp套接字创建    sock = socket()    sock.bind(ADDR)    sock.Listen(5)    print("Listen the port %s" % PORT)    # 循环连接客户端    while True:        try:            connfd, addr = sock.accept()            print("Connect from", addr)        except KeyboardInterrupt:            sock.close()            return        # 为连接进来的客户端创建单独的线程        t = FTPServer(connfd)  # 使用自定义线程类创建线程        t.setDaemon(True)  # 主线程退出,分之线程终止服务        t.start()if __name__ == '__main__':    main()

---------------FTP 客户端

"""ftp文件服务客户端"""from socket import *import timeimport sys# 服务端地址ADDR = ("127.0.0.1", 8888)# 实现具体的请求功能class FTPClIEnt:    def __init__(self, sock):        self.sock = sock    def do_List(self):        self.sock.send(b"List")  # 发送请求        result = self.sock.recv(128).decode()  # 回复 字符串        # 根据回复分情况讨论        if result == 'OK':            # 接收文件列表            file = self.sock.recv(1024 * 1024).decode()            print(file)        else:            print("文件库为空")    # 下载文件    def do_get(self, filename):        data = "RETR " + filename        self.sock.send(data.encode())  # 发送请求        # 等回复        result = self.sock.recv(128).decode()        if result == 'OK':            # 接收文件            f = open(filename, 'wb')            while True:                data = self.sock.recv(1024)                if data == b"##":                    break                f.write(data)            f.close()        else:            print("文件不存在")    # 上传文件    def do_put(self, filename):        # 本地判断,防止文件路径写错        try:            f = open(filename, 'rb')        except:            print("该文件不存在")            return        # 上传 put 后可能是路径/home/tarena/abc,提取真正的文件名        filename = filename.split('/')[-1]        data = "STOR " + filename        self.sock.send(data.encode())  # 发送请求        # 等回复        result = self.sock.recv(128).decode()        if result == 'OK':            # 发送文件            while True:                data = f.read(1024)                if not data:                    time.sleep(0.1)                    self.sock.send(b"##")  # 文件发送完毕                    break                self.sock.send(data)            f.close()        else:            print("文件已经存在")    # 退出    def do_exit(self):        self.sock.send(b"EXIT")        self.sock.close()        sys.exit("谢谢使用")def main():    # 创建套接字    sock = socket()    sock.connect(ADDR)    # 实例化功能类对象    ftp = FTPClIEnt(sock)    while True:        print("============ 命令选项==============")        print("***           List           ***")        print("***         get  file        ***")        print("***         put  file        ***")        print("***           exit           ***")        print("==================================")        cmd = input("请输入命令:")        if cmd == "List":            ftp.do_List()        elif cmd[:3] == "get":            filename = cmd.split(' ')[-1]  # 提取文件名            ftp.do_get(filename)        elif cmd[:3] == "put":            filename = cmd.split(' ')[-1]  # 提取文件名            ftp.do_put(filename)        elif cmd == "exit":            ftp.do_exit()        else:            print("请输入正确命令")if __name__ == '__main__':    main()

                                             I O 阻塞 
"""非阻塞IO套接字对象 --》 非阻塞"""from socket import *import time # 打开日志文件f = open("my.log",'a') # 创建tcp套接字sockfd = socket()sockfd.bind(('0.0.0.0',8888))sockfd.Listen(5) # 设置套接字的非阻塞 # sockfd.setblocking(False) # 超时检测时间sockfd.settimeout(3)while True:    print("Waiting for connect")    try:        connfd,addr = sockfd.accept() # 阻塞等待        print("Connect from",addr)    except BlockingIOError as e:        # 干点别的事        msg = "%s : %s\n"%(time.ctime(),e)        f.write(msg)        time.sleep(2)    except timeout as e:        # 干点别的事        msg = "%s : %s\n"%(time.ctime(),e)        f.write(msg)    else:        # 正常有客户端连接        data = connfd.recv(1024)        print(data.decode())

IO 多路复用

定义 : 同时监控多个IO事件,当哪个IO事件准备就绪执行哪个IO事件,以此形成可以同时处理多个IO
的行为,避免一个IO阻塞造成其他IO均无法执行,提高了IO执行效率

具体方案:
select 方法 :windows linux unix
poll 方法 : linux unix
epoll 方法: linux

select 方法 : help(select.select) #可以查看帮助文档
rs,ws,xs = select(rList,wList,xList[,timeout])
功能:监控IO事件,阻塞等待IO发生
参数: rList 列表 读IO列表 添加等待发生的或者可读的IO事件
wList 列表 写IO列表 存放要可以主动处理的或者可写的IO事件
xList 列表 异常IO列表 存放出现异常要处理的IO事件
timeout 超时时间

      返回值: rs    列表     rList中准备就绪的IO                   ws   列表     wList中准备就绪的IO                   xs    列表      xList中准备就绪的IO 

总结

以上是内存溢出为你收集整理的python_ftp全部内容,希望文章能够帮你解决python_ftp所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1188739.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存