博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 之selectors 实现文件上传下载
阅读量:6955 次
发布时间:2019-06-27

本文共 7328 字,大约阅读时间需要 24 分钟。

1.文件目录

selector_FTP ——————

       clientfile ——————  存放用户文件路径

       selector_client.py——

selector_server.py——

       serverfile —————— 存放服务器文件路径

 

注:实现的简约版的FTP,不支持断点续传、断点下载等操作

且只支持普通上传下载 用selector实现,支持多条客户端链接同时下载、上传 ,切勿多个客户端同时上传、下载同一个文件。

 

服务端

selector_server.py

def get(conn,cmd): 下载文件

def put(conn,cmd): 上传文件

def accept(sock, mask): selector 注册方法

def read(conn, mask): selector 注册方法

selector_server.py

def get(conn,cmd): 下载文件

def put(conn,cmd): 上传文件

def progress(recive_size,file_size,tips) 显示下载进度方法

 

例子:

clientfile 里面有一个3D.pdf  在客户端输入命令 put 3D.pdf  后 serverfile 文件夹下会有3D.pdf 

serverfile 里面有一个test.zip  在客户端输入命令 get test.zip  后 clientfile  文件夹下会有test.zip

服务器端:

#!/usr/bin/env python# -*- coding: utf-8 -*-# Author: wenjinLiimport selectorsimport socketimport os,sysimport timeimport errnoBASE_DIR = os.path.dirname(os.path.abspath(__file__))sel = selectors.DefaultSelector()def get(conn,cmd):    if len(cmd.split()) > 1:        filename = cmd.split()[1]        file_path = '%s/serverfile/%s' % (BASE_DIR, filename) #文件路径        print(file_path)        if os.path.isfile(file_path): #判断文件是否存在            client_file_size = 0            file_size = os.stat(file_path).st_size #获得文件大小            conn.send(str(file_size).encode()) #将文件大小传给客户端            time.sleep(0.3)            while True:                with open(file_path, 'rb') as f:                    try:                        for line in f:                            client_file_size += len(line) #记录已经传送的文件大小                            conn.sendall(line)                            print(client_file_size, file_size)                    except IOError as e:                        if e.errno != errno.EAGAIN: # errno.EAGAIN 缓冲区满 等待下                            raise                        else:                            time.sleep(0.1) #等待0.1s进行下一次读取                if client_file_size >= int(file_size): #文件传送完毕                    print('break')                    break        else:            conn.sendall('405'.encode())  # 文件不存在    else:        conn.sendall('401'.encode())  # 命令不存在,无法操作def put(conn,cmd):    filename = cmd.split()[1]    filename = "%s/serverfile/%s" % (BASE_DIR, filename) #文件路径    with open(filename, 'ab') as f:        data = conn.recv(1024).decode()        total_size = int(data)        if total_size == '405' or total_size == '401': #文件不存在 或命令有误            return None        current_size = 0        while current_size <= total_size:            try:                recivesize = total_size - current_size                if recivesize > 1024:                    recivesize = 1024                data = conn.recv(recivesize)                if not data: #客户端断开                    print('closing', conn)                    sel.unregister(conn)                    conn.close()                    break                current_size += len(data)                f.write(data)            except IOError as e:                if e.errno != errno.EAGAIN:                    raise                else:                    time.sleep(0.1)        print('接收完毕')def accept(sock, mask):    conn, addr = sock.accept()  # Should be ready    conn.setblocking(False)    sel.register(conn, selectors.EVENT_READ, read)def read(conn, mask):    data = conn.recv(1000)  # Should be ready    if data:        print(data)        command_str = data.decode()        print(command_str)        if command_str.split()[0] == 'put':            put(conn, command_str)        elif command_str.split()[0] == 'get':            get(conn,command_str)        else:            conn.send(b'404') # Hope it won't block    else:        print('closing', conn)        sel.unregister(conn)        conn.close()sock = socket.socket()sock.bind(('localhost', 1112))sock.listen(100)sock.setblocking(False)sel.register(sock, selectors.EVENT_READ, accept)while True:    events = sel.select()    for key, mask in events:        callback = key.data        callback(key.fileobj, mask)

 用户端:

#!/usr/bin/env python# -*- coding: utf-8 -*-# Author: wenjinLiimport socketimport timeimport os,sysimport errnoBASE_DIR = os.path.dirname(os.path.abspath(__file__))def get(s,command):    '''下载'''    if len(command.split()) == 2:        s.send(command.encode()) #通知服务器 要上传文件了    else:        print('下载命令有误')    filename = command.split()[1]    filename = "%s/clientfile/%s" % (BASE_DIR, filename) #本地地址    with open(filename, 'ab') as f:        data = s.recv(1024)        print(data)        data = data.decode()        total_size = int(data)        if total_size == '405':            print('文件不存在')            return None        current_size = 0        while current_size <= total_size:            try:                recivesize = total_size - current_size                if recivesize > 1024:                    recivesize = 1024                data = s.recv(recivesize)                if not data:                    break                current_size += len(data)                progress(current_size, total_size, '下载中...') #打印进度                print(current_size, total_size)                f.write(data)            except IOError as e:                if e.errno != errno.EAGAIN:                    raise                else:                    time.sleep(0.1) #若 系统缓存已满则等带0.1秒后开始        print('接收完毕')def put(s,command):    '''上传'''    if len(command.split()) == 2:        s.send(command.encode()) #告诉服务器要上传文件    else:        print('上传命令有误')    if len(command.split()) > 1:        filename = command.split()[1]        file_path = '%s/clientfile/%s' % (BASE_DIR, filename)        print(file_path)        if os.path.isfile(file_path):            current_file_size = 0            file_size = os.stat(file_path).st_size            s.send(str(file_size).encode())            time.sleep(0.3)            with open(file_path, 'rb') as f:                try:                    for line in f:                        s.sendall(line)                        current_file_size += len(line)                        progress(current_file_size, file_size, '上传中...')                        print(current_file_size,file_size)                except IOError as e:                    if e.errno != errno.EAGAIN:  # errno.EAGAIN 缓冲区满 等待下                        raise                    else:                        time.sleep(0.1)  # 等待0.1s进行下一次读取        else:            s.send('405'.encode())            print('文件不存在')    else:        s.send('401'.encode())        print('命令不存在')def progress(recive_size,file_size,tips):    '''***代表加载 _____表示还未加载部分'''    lensize = 100    percent = float(recive_size) / float(file_size)    recivenumber = '*' * int(percent * lensize)  # 已经加载的所占格数    leftnumber = '_' * (lensize - int(percent * lensize))  # 未加载的所占格数    sys.stdout.write('%s:%d%% [%s]\n' % (tips, percent * lensize, recivenumber + leftnumber))    sys.stdout.flush()if __name__ == '__main__':    HOST = 'localhost'    PORT = 1112    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    s.connect((HOST,PORT))    while True:        msg = input('>>>请输入操作命令:').strip()        if len(msg) == 0:            continue        command = msg.split()[0]        if command == 'get':            '''下载'''            get(s,msg)        elif command == 'put':            '''上传'''            put(s, msg)        elif command == 'exit':            print('成功退出')            break        else:            continue    s.close()

 

转载于:https://www.cnblogs.com/nanfengxiaojin/p/6942243.html

你可能感兴趣的文章
mysql 分区类型详解
查看>>
ORACLE同义词总结
查看>>
iOS 设备类型和版本判断
查看>>
ios字体设置
查看>>
【SICP练习】51 练习2.19
查看>>
solveCrossprod求 X'X的逆, ( X' == t(X), 即X的行列变换矩阵 )
查看>>
PostgreSQL column cryptographic use pgcrypto extension and optional openssl lib
查看>>
通过支付宝服务中断事件看系统可靠性和YunOS的可靠性
查看>>
oVirt VM (CentOS) template & clone
查看>>
Linux内核编译与启动流程
查看>>
Flutter框架分析(二)-- 初始化
查看>>
mac更新系统后Android studio Git不能用,提示missing xcrun at
查看>>
微信公众号排版
查看>>
常用布局-1
查看>>
Swift基础语法学习-3.类型转换
查看>>
向你安利了一个编辑器,并丢给你一堆插件
查看>>
Flutter 入门之 ListTile 使用指南
查看>>
Android Material Design控件使用(一)——ConstraintLayout 约束布局
查看>>
好程序员Web前端分享程序的三大结构(一)
查看>>
Mac下如何编译 FFmpeg的SO库,为Android使用
查看>>