zoukankan      html  css  js  c++  java
  • 32 实现大文件的传输、切换目录

    首先回顾一下小文件的传输

    import socket
    import os
    import json
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8001))
    menu = {"1": "upload", "2": "download"}
    for k, v in menu.items():
        print(k, v)
    num = input("请输入功能选项:")
    if num == "1":
        dic = {"opt": menu.get(num), "filename": None, "content": None}
        file_path = input("请输入一个绝对路径:")
        filename = os.path.basename(file_path)
        with open(file_path, "r", encoding="utf-8") as f:
            content = f.read()
        dic["filename"] = filename
        dic["content"] = content
        str_dic = json.dumps(dic)
        sk.send(str_dic.encode("utf-8"))
    
    elif num == "2":
        pass
    小文件传输——client
    import socket
    import json
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 8001))
    sk.listen()
    conn, addr = sk.accept()
    str_dic = conn.recv(9090).decode("utf-8")
    dic = json.loads(str_dic)
    if dic["opt"] == "upload":
        filename = "1" + dic["filename"]
        with open(filename, "w", encoding="utf-8") as f:
            f.write(dic["content"])
    elif dic["opt"] == "download":
        pass
    
    conn.close()
    sk.close()
    小文件传输——server

    粘包
    tcp协议粘包,udp不粘包
    合包机制(nagle算法)-- 发生在发送端

      拆包机制-- 发生在发送端 ,由于最大传输单元(Maximum Transmission Unit,MTU)的限制,会把数据拆包进行发送

    subprocess.Popen() 执行系统命令

    解决粘包
    新模块 struct
    struct.pack(type,num)
    type:是num的类型
    num :是一个数字
    r = struct.pack(type,num) 把一个数字打包成一个四字节的bytes

    struct.unpack(type,r)
    功能:解包,把r解成原数字,结果是一个元组,原数字在元组的下标位0的位置

    大文件传输:

    import socket
    import os
    import json
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8001))
    menu = {"1": "upload", "2": "download"}
    for k, v in menu.items():
        print(k, v)
    num = input("请输入功能选项:")
    if num == "1":
        dic = {"opt": menu.get(num), "filename": None, "filesize": None}
        file_path = input("请输入一个绝对路径:")  # 文件的绝对路径
        filename = os.path.basename(file_path)  # 文件名字
        filesize = os.path.getsize(file_path)  # 获取用户输入的路径中文件的大小
    
        dic["filename"] = filename
        dic["filesize"] = filesize
        str_dic = json.dumps(dic)
        sk.send(str_dic.encode("utf-8"))  # 将被填充完成的字典先发送给服务器
        sk.recv(1024)  # 为什么要有一个recv?
        #  因为上边send字典时,如果程序执行过快,可能会马上执行到下边的send(content)
        #  此时有可能会发生粘包,所以在此中间加一个recv,为了避免粘包
        with open(file_path, "rb") as f:
            while filesize:
                content = f.read(1024)
                sk.send(content)
                filesize -= len(content)
    
    elif num == "2":
        pass
    client
    import socket
    import json
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 8001))
    sk.listen()
    conn, addr = sk.accept()
    str_dic = conn.recv(100).decode("utf-8")
    conn.send(b'ok')
    # str_dic = {"opt":menu.get(num),"filename":None,"filesize":None}
    dic = json.loads(str_dic)
    if dic["opt"] == "upload":
        filename = "1" + dic["filename"]
        with open(filename, "ab") as f:
            while dic['filesize']:
                content = conn.recv(1024)
                f.write(content)
                dic['filesize'] -= len(content)
    
    elif dic["opt"] == "download":
        pass
    
    conn.close()
    sk.close()
    server

      

    切换目录

    import socket
    import os
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 8080))
    sk.listen()
    conn, addr = sk.accept()
    
    
    def send_data(conn, path):
        '''你给我一个目录,我把目录发给client'''
        lis_dir = os.listdir(path)
        str_dir = '--'.join(lis_dir)
        conn.send(str_dir.encode('utf-8'))
    
    
    abs_path = conn.recv(1024).decode('utf-8')  # 获取用户输入的绝对路径
    current_dir = abs_path + '/'  # 以下再处理,都要根据当前路径去处理,无论是返回上一层,还是进入下一层
    send_data(conn, current_dir)  # 把用户输入的路径下的所有文件及文件夹返回给客户端
    
    # C:/Program Files (x86)/Common Files
    while 1:
        cmd = conn.recv(1024).decode('utf-8')
        if cmd == '..':
            current_dir = current_dir.split('/')[:-2]
            current_dir = '/'.join(current_dir) + '/'
            # if 如果当前是C盘:
            #     就返回给客户端告诉说没有上一层了!
            send_data(conn, current_dir)
        else:
            filename = cmd.split(' ')[1]  # 获取用户输入的文件名字
            current_dir += filename + '/'  # 将文件名字添加到当前路径下,组成一个完整的新路径
            if os.path.isdir(current_dir):  # 如果客户输入的文件名字是一个文件夹
                send_data(conn, current_dir)
            else:  # 如果不是一个文件夹
                conn.send(b'bu shi wen jian jia')
    
    # conn.close()
    # sk.close()
    server
    import socket
    import os
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 8080))
    
    abs_path = input('请输入您的根目录:')
    sk.send(abs_path.encode('utf-8'))
    current_dir = sk.recv(1024).decode('utf-8')
    print(current_dir.split('--'))
    
    while 1:
        cmd = input('请输入>>>')
        # cd + 文件夹      ..
        if cmd == '..':
            sk.send(cmd.encode('utf-8'))
            current_dir = sk.recv(1024).decode('utf-8')
            print(current_dir.split('--'))
        if cmd == 'cd':
            filename = input('请输入一个文件夹名:')
            sk.send((cmd + ' ' + filename).encode('utf-8'))
            current_dir = sk.recv(1024).decode('utf-8')
            print(current_dir.split('--'))
    
    sk.close()
    client
  • 相关阅读:
    having——至少被订购过两回的订单
    产品——仓库表查询
    SQL 聚集函数使用
    select count(*)和select count(1)的区别 (转)
    SpringAOP 通知(advice)
    Spring AOP 实现原理与 CGLIB 应用
    cglib 动态代理基础篇
    模仿Struts2的Interceptor拦截器实现
    利用JDK动态代理机制实现简单拦截器
    java多线程总结二:后台线程(守护线程)
  • 原文地址:https://www.cnblogs.com/zhuangdd/p/12713520.html
Copyright © 2011-2022 走看看