zoukankan      html  css  js  c++  java
  • 利用生成器制作一个简单的客户端接收文件的进度条

      一、首先看一个生成器的例子:

    def run():
        count = 0
        while 1:
            n = yield count
            print(n,'---',count)
            count += 1
    
    g = run()
    #一开始调用__next__方法不会唤醒,只有用send方法才能打印
    g.__next__()
    ##send的用法
    g.send('whw')
    g.send('whw1')
    g.send('whw2')
    g.send('whw3')
    g.send('whw4')

      这里,我们在第一次使用__next__()方法是是不会唤醒生成器的,后面加上send()方法可以打印出相应的结果:

      二、在客户端利用生成器加进度条的简单思路:

      大致的过程为:我们先定义一个当前文件传输时传输的数据占文件总大小的比例current_percent变量,注意这个current_percent是不断叠加的:当进行第二次传输时变成了第一次传输的百分比与第二次传输的百分比的和...以此类推;另外,我们把每一次接收的“current_percent”的“当前值”赋值给另外一个变量last_percent,只要current_percent大于last_percent,表明文件就没有存完,只有当二者相等的时候才表示文件全部传完——也就是说,我们的迭代条件就是current_percent >last_percent

      生成器函数的代码如下:

    def progress_bar(total_size, current_percent=0, last_percent=0):
        '''进度条功能'''
        while 1:
            received_size = yield current_percent
            current_percent = int(received_size / total_size * 100)
            if current_percent > last_percent:
                print("*" * int(current_percent / 2) + "{percent}%".format(percent=current_percent), end='
    ',
                      flush=True)
                # 把本次循环的percent赋值给last
                last_percent = current_percent  

      调用函数的代码如下:

    progress_generator = progress_bar(file_size)
    progress_generator.__next__()
    
    #其他代码
    
    progress_generator.send(receive_size)

      三、程序的server端与client端的代码如下:

    import os
    import socket
    import json
    
    # C:UsersdellDesktop	est
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    STATUS_CODE = {
            200: "开始发送文件!",
            201: "文件不存在!",
        }
    
    def send_response(conn,status_code,*args,**kwargs):
        #制作消息
        data = kwargs
        data['status_code'] = status_code
        data['status_msg'] = STATUS_CODE[status_code]
        data['fill'] = ''
        #扩展data字典,将file_size键加进去
        data.update(kwargs)
        #二进制的消息
        bytes_data = json.dumps(data).encode('utf-8')
        #制作定长报头
        if len(bytes_data) < 1024:
            # zfill——返回指定长度字符串,原字符串右对齐,前面填充0
            data['fill'] = data['fill'].zfill(1024-len(bytes_data))
            bytes_data = json.dumps(data).encode('utf-8')
        conn.send(bytes_data)
    
    def get(conn,addr,filename):
        while 1:
            if not filename:#空指令,断开链接
                print('connection is lost!')
                del conn,addr
                break
            file_path = os.path.join(BASE_DIR,'server',filename)
            #如果文件存在
            if os.path.isfile(file_path):
                #得出文件的大小
                file_size = os.stat(file_path).st_size
                send_response(conn,200,file_size=file_size)
                #开始发送文件
                f = open(file_path,'rb')
                for line in f:
                    conn.send(line)
                else:
                    print('文件传输成功!')
                f.close()
            else:
                send_response(conn,201)
    
    
    
    def run():
        whw_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        whw_server.bind(('127.0.0.1',9999))
        whw_server.listen(5)
        print('Listening......')
        conn,addr = whw_server.accept()
        while 1:
            try:
                res = conn.recv(8096)
                cmds = res.decode('utf-8').split()
                print('收到命令:',res.decode('utf-8'))
                if cmds[0] == 'get':
                    get(conn,addr,cmds[1])
            except ConnectionResetError:
                break
        conn.close()
    
    
    if __name__ == '__main__':
        run()
    server.py
    import os
    import socket
    import json
    
    # C:UsersdellDesktop	est
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    def progress_bar(total_size, current_percent=0, last_percent=0):
        '''进度条功能'''
        while 1:
            received_size = yield current_percent
            current_percent = int(received_size / total_size * 100)
            if current_percent > last_percent:
                print("*" * int(current_percent / 2) + "{percent}%".format(percent=current_percent), end='
    ',
                      flush=True)
                # 把本次循环的percent赋值给last
                last_percent = current_percent
    
    def send_message(whw_sock,filename,**kwargs):
        '''给客户端发送报头'''
        msg_data = {
            'file_name':filename,
            'fill':''#做定长
        }
        msg_data.update(kwargs)
        bytes_msg = json.dumps(msg_data).encode('utf-8')
        if len(msg_data) < 1024:#定长的报头
            msg_data['fill'] = msg_data['fill'].zfill(1024-len(bytes_msg))
            bytes_msg = json.dumps(msg_data).encode('utf-8')
        whw_sock.send(bytes_msg)
    
    
    def get_response(whw_sock):
        """获取服务器端返回的信息"""
        data = whw_sock.recv(1024)
        return json.loads(data.decode('utf-8'))
    
    
    def get(whw_sock,cmds):
        filename = cmds[1]
        response = get_response(whw_sock)
        # file_size与server端send_response(conn,200,file_size=file_size)对对应
        file_size = response.get('file_size')
        receive_size = 0
        # 进度条功能
        progress_generator = progress_bar(file_size)
        progress_generator.__next__()
        #注意wb方式打开
        f = open('%s.download' % filename, 'wb')
        # 循环接收
        while receive_size < file_size:
            if file_size - receive_size < 8192:  # last recv
                data = whw_sock.recv(file_size - receive_size)
            else:
                data = whw_sock.recv(8192)
            receive_size += len(data)
            f.write(data)
            # 打印进度条
            progress_generator.send(receive_size)
        else:
            print('
    ')
            print('---file [%s] recv done,received size [%s]---' % (filename, file_size))
            f.close()
            os.replace('%s.download' % filename, filename)
    
    def run():
        whw_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        whw_sock.connect(('127.0.0.1',9999))
        while 1 :
            inp = input('>>>:').strip()
            if not inp:
                continue
            whw_sock.send(inp.encode('utf-8'))
            cmds = inp.split()
            if cmds[0] == 'get':
                get(whw_sock,cmds)
    
    
    if __name__ == '__main__':
        run()
    client.py

      四、演示如下:

  • 相关阅读:
    把一件简单的事情做好你就不简单了
    一个经验尚浅的码农五年软件开发的一点自我总结,对工作五年的反思~
    我就是一名房地产经纪人!不是中介,谁能明白我们呢?
    我与父辈的酒局
    郎意难坚,侬情自热(文/王路)
    红灯须硬闯,马路要横穿(文/王路)
    孩子,你慢慢来
    职场六年后的一点点感言
    有幸见到一朵花的绽放
    当你遇到她
  • 原文地址:https://www.cnblogs.com/paulwhw/p/9075221.html
Copyright © 2011-2022 走看看