zoukankan      html  css  js  c++  java
  • 使用IO多路复用selectors模块写上传下载功能

    import selectors
    import socket
    import struct
    import json
    import os,sys
    BASEDIR = os.path.dirname(__file__)
    
    class Server:
        def __init__(self):
            self.dic = {}
            self.sel = selectors.DefaultSelector()
            self.makesock()
            self.handle()
    
        def makesock(self):
            sock = socket.socket()
            sock.bind(('127.0.0.1',8099))
            sock.listen(5)
            sock.setblocking(False)
            self.sel.register(sock,selectors.EVENT_READ,self.accept)
    
        def handle(self):
            while True:
                event = self.sel.select()
                for key,mask in event:
                    func = key.data
                    func(key.fileobj,mask)
    
        def accept(self,sock,mask):
            conn,addr = sock.accept()
            self.sel.register(conn,selectors.EVENT_READ,self.read)
            self.dic[conn] = {}
    
        def read(self,conn,mask):
            if not self.dic[conn]:
                try:
                    length = struct.unpack('i',conn.recv(4))[0]
                    cmd = json.loads(conn.recv(length).decode('utf8'))
                except Exception as e:
                    print(e)
                    conn.close()
                    self.sel.unregister(conn)
                    return
                if cmd['action'] == 'put':
    
                    conn.send(b'0')
                    f = open(os.path.basename(cmd['filename']),'wb')
                    if not cmd['filesize']:
                        f.close()
                        return
                    self.dic[conn] = cmd
                    self.dic[conn]['data_len'] = 0
                    self.dic[conn]['file'] = f
                elif cmd['action'] == 'get':
                    path = os.path.join(BASEDIR,cmd['filename'])
                    if os.path.exists(path) and os.path.isfile(path):
                        filesize = os.path.getsize(path)
                        # print(filesize)
                        if filesize:
                            f = open(path,'rb')
                            self.dic[conn] = cmd
                            self.dic[conn]['file'] = f
                            conn.send(b'2')
                            conn.send(str(filesize).encode('utf8'))
                        else:
                            conn.send(b'1')
                    else:
                        conn.send(b'0')
            else:
                if hasattr(self,self.dic[conn]['action']):
                    func = getattr(self,self.dic[conn]['action'])
                    func(conn)
    
        def get(self,conn):
    
            data = self.dic[conn]['file'].read(1024)
            if not data:
                self.dic[conn]['file'].close()
                self.dic[conn] = {}
                return
            status = conn.recv(1)
            conn.send(data)
    
        def put(self,conn):
            if self.dic[conn]['data_len'] == self.dic[conn]['filesize']:
                self.dic[conn]['file'].close()
                self.dic[conn] = {}
                return
            data = conn.recv(1024)
            self.dic[conn]['file'].write(data)
            self.dic[conn]['data_len'] += len(data)
    
    if __name__ == '__main__':
        Server()
    import socket
    import struct
    import json
    import os,sys
    
    class Client:
        def __init__(self,ip_port):
            self.ip_port = ip_port
            self.makeconn()
            self.handle()
    
        def makeconn(self):
            self.conn = socket.socket()
            self.conn.connect(self.ip_port)
    
        def handle(self):
            while True:
                cmd = input(">>>")
                cmd = cmd.split()
                if hasattr(self,cmd[0]):
                    func = getattr(self,cmd[0])
                    func(*cmd)
    
        def jindu(self,size,filesize):
            baifen_len = size / filesize
            baifen = int(baifen_len * 100)
            isok = 0
            if baifen == 100:
                r = '
    %s>%d%%
    ' % ('=' * baifen, baifen,)
                isok =  1
            else:
                r = "
    %s>%d%%"%('='*baifen,baifen,)
            sys.stdout.write(r)
            sys.stdout.flush
            return isok
    
        def get(self,*cmd):
            data = {
                "action" : "get",
                "filename" : cmd[1]
            }
            data = json.dumps(data).encode('utf8')
            length = struct.pack('i',len(data))
            self.conn.send(length)
            self.conn.send(data)
            status = self.conn.recv(1).decode('utf-8')
            if status == '0':
                print("文件不存在")
                return
            f = open(os.path.basename(cmd[1]),'wb')
            if status == '1':
                f.close()
                return
            filesize = self.conn.recv(1024).decode('utf8')
            filesize = int(filesize)
            file_len = 0
            while True:
                self.conn.send(b'0')
                file_data = self.conn.recv(1024)
                file_len += len(file_data)
                f.write(file_data)
                if self.jindu(file_len,filesize):
                    f.close()
                    break
    
        def put(self,*cmd):
            data = {
                "action": "put",
                "filename": cmd[1],
            }
            if os.path.exists(cmd[1]) and os.path.isfile(cmd[1]):
                filesize = os.path.getsize(cmd[1])
                data['filesize'] = filesize
                data = json.dumps(data).encode('utf8')
                length = struct.pack('i', len(data))
                self.conn.send(length)
                self.conn.send(data)
                status = self.conn.recv(1)
                data_len = 0
                with open(cmd[1],'rb') as f:
                    while True:
                        data = f.read(1024)
                        if not data: return
                        self.conn.send(data)
                        data_len += len(data)
                        if self.jindu(data_len, filesize):
                            break
            else:
                print("文件不存在")
                return
    
    
    
    if __name__ == '__main__':
        c = Client(('127.0.0.1',8099))
        c.handle()
  • 相关阅读:
    二叉树专题
    强化学习的几个基本概念
    LeetCode #111 二叉树的最小深度
    NC127 最长公共子串
    快速排序
    NC78 反转链表
    《合作的进化》读后总结
    Optional和Stream的map与flatMap
    最爱的小工具,谁用谁知道!
    SpringBoot应用启动过程分析
  • 原文地址:https://www.cnblogs.com/xieys-1993/p/11724170.html
Copyright © 2011-2022 走看看