当前位置: 移动技术网 > IT编程>脚本编程>Python > python selectors模块实现 IO多路复用机制的上传下载

python selectors模块实现 IO多路复用机制的上传下载

2019年09月12日  | 移动技术网IT编程  | 我要评论

叶锦茹,蓝色导航,巨菊攻受


import selectors
import socket
import os,time

base_dir = os.path.dirname(os.path.abspath(__file__))

class server:
    # sel = selectors.defaultselector()
    def __init__(self):
        self.ip_port=('127.0.0.1',8080)
        self.sel=selectors.defaultselector()
        #根据平台选择最佳的io多路机制,比如linux就会选择epoll

        self.dic = {}
        self.create_sock()
        self.handle()

    def create_sock(self):
        sock = socket.socket()
        sock.bind(('localhost', 1234))
        sock.listen(100)
        # sock.setblocking(false)
        #注册监听对象,绑定accept
        self.sel.register(sock, selectors.event_read, self.accept
    def handle(self):
        while true:
            #sel监听sock变化,当sock实例化时,赋值给events,通过回调函数触发
            #key.data(key.fileobj,mask)  accept(sock,mask),
            #当有客户端连接时通过accept注册到read……
            events = self.sel.select()  # [sock,conn1,conn2]
            for key, mask in events:
                callback = key.data  # sel  accept  sel read
                callback(key.fileobj, mask)  #accept(sock,mask),read(conn1,mask)……
    def accept(self,sock, mask):
        print('登录服务端---')
        conn, addr = sock.accept()  # should be ready
        print('accepted', conn, 'from', addr)
        # conn.setblocking(false)
        self.sel.register(conn, selectors.event_read, self.read)
        self.dic[conn]={}
    def read(self,conn, mask):

        try:
            if not self.dic[conn]:

                data = conn.recv(1024)
                try:
                    cmd, filename, filesize = str(data.decode("utf-8")).split("|")
                    self.dic[conn] = {"cmd": cmd, "filename": filename, "filesize": filesize, "hasreceived": 0}
                except exception as e:

                    cmd, filename = str(data.decode("utf-8")).split("|")
                    self.dic[conn] = {"cmd": cmd, "filename": filename,"filesize": os.path.getsize(os.path.join(base_dir, "load", filename)),"hassended": 0}

                if cmd=='put':#上传
                    conn.send('ok'.encode('utf8'))
                if cmd=='get':#下载
                    conn.send(str(self.dic[conn]['filesize']).encode('utf8'))
            else:
                if self.dic[conn].get('cmd',none):
                    cmd =self.dic[conn].get('cmd')
                    if hasattr(self,cmd):
                        func=getattr(self,cmd)
                        func(conn,mask)#反射命令分发
                    else:
                        print('error')
        except exception as e:
            print(e,conn,'断开连接')
            conn.close()
            self.sel.unregister(conn)

    def put(self,conn,mask):
        filename=self.dic[conn]['filename']
        filesize = self.dic[conn]['filesize']

        path = os.path.join(base_dir, "upload", filename)
        data = conn.recv(1024)
        conn.send("success".encode("utf-8"))
        self.dic[conn]['hasreceived'] += len(data)
        with open(path, "ab") as f:
            f.write(data)
        if self.dic[conn]['hasreceived'] == self.dic[conn]['filesize']:
            self.dic[conn] = {}
            print("上传结束")
        #少写一步


    def get(self, conn, mask):

        filename = self.dic[conn]['filename']
        path = os.path.join(base_dir, "load", filename)

        with open(path, "rb") as f:
            f.seek(self.dic[conn]["hassended"], 0)
            data = f.read(1024)
            conn.send(data)
            self.dic[conn]['hassended'] += len(data)
            if self.dic[conn]['hassended'] == self.dic[conn]["filesize"]:
                self.dic[conn] = {}
                print("下载结束")
        time.sleep(0.5)


if __name__ == "__main__":
    server()


import os, time, sys

base_dir = os.path.dirname(os.path.abspath(__file__))

import socket
import selectors


class selectftpclient:
    def __init__(self):

        self.port = ("127.0.0.1", 8001)
        self.create_socket()
        self.command_fanout()

    def create_socket(self):
        try:
            self.sock = socket.socket()
            self.sock.connect(self.port)
            print("连接ftp成功!")
        except exception:
            print("连接失败!")

    def command_fanout(self):
        while true:
            cmd = input(">>>").strip()
            if cmd == "exit()":
                break
            cmd, file = cmd.split()
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                func(cmd, file)
            else:
                print('调用错误!')

    # 上传
    def put(self, cmd, file):
        if os.path.isfile(file):
            filename = os.path.basename(file)
            filesize = os.path.getsize(file)
            fileinfo = "%s|%s|%s" % (cmd, filename, filesize)
            self.sock.send(bytes(fileinfo, encoding="utf-8"))
            recvstatus = self.sock.recv(1024)
            hassend = 0
            if str(recvstatus, encoding="utf-8") == 'ok':
                with open(file, "rb") as f:
                    while filesize > hassend:
                        contant = f.read(10)
                        recv_size = len(contant)
                        self.sock.send(contant)
                        hassend += recv_size
                        s = str(int(hassend / filesize * 100)) + "%"
                        print("正在上传文件:" + filename + "   已经上传:  " + s)
                        time.sleep(0.5)
                print("%s文件上传完毕" % (filename,))
            else:
                print("文件不存在")

    # 下载
    def get(self, cmd, file):

        fileinfo = "%s|%s" % (cmd, file)
        self.sock.send(bytes(fileinfo, encoding="utf-8"))
        filesize = int(self.sock.recv(10).decode("utf-8"))

        f = open(file, "ab")
        i = 0
        while i < filesize:
            self.sock.send("ok".encode("utf-8"))
            data = self.sock.recv(10)
            f.write(data)
            i += len(data)
            s = str(int(i / filesize * 100)) + "%"
            print("正在上传文件:" + file + "   已经下载:  " + s)

        print("下载完成")
        f.close()


if __name__ == "__main__":
    selectftpclient()

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网