zoukankan      html  css  js  c++  java
  • 32 解决黏包 struct模块 目录切换 文件传输

    主要内容 :

     1 . struct 模块 : 可以把一种数据类型, 如数字,转换成固定长度的bytes.

            -2147483648 ------ 2147483648  4bytes

    import struct
    a = 123
    abs_len_by = struct.pack('i', a)
    print(abs_len_by,len(abs_len_by))    #b'{x00x00x00' 4 
    ret = struct.unpack('i',abs_len_by)
    print(ret)                           #(123,)返回值是一个元祖  

    2 . 大文件的传输

      a: 版本一 : 解决黏包问题的大文件传输

      服务器端代码 : 

    import socket
    import json
    import struct
    sk = socket.socket()
    sk.bind(("127.0.0.1",8091))
    sk.listen()
    conn, addr = sk.accept()
    b_len_dic = conn.recv(4)
    len_dic = struct.unpack('i', b_len_dic)[0]# 获取到int类型字典的长度,
    # unpack得到的是一个元组,要取下标为0的位置
    str_dic = conn.recv(len_dic).decode('utf-8')
    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()
    

      客户端代码:

    import socket
    import os
    import json
    import struct
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8091))
    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("请输入一个绝对路径:")# 文件的绝对路径
        # E:Python S14day32实现大文件的传输11.mp4
        filename = os.path.basename(file_path)# 文件名字
        filesize = os.path.getsize(file_path)# 获取用户输入的路径中文件的大小
        dic["filename"] = filename
        dic["filesize"] = filesize
        str_dic = json.dumps(dic)
        len_dic = len(str_dic)# 获取到字典的长度,是一个int类型的数据   46   146
        b_len_dic = struct.pack('i',len_dic)# 用一个4bytes的数据表示字典的长度
        sk.send(b_len_dic + str_dic.encode("utf-8"))# 将bytes类型的字典的长度 + bytes类型的字典的内容,一起发送给服务器
        with open(file_path, "rb") as f:
            while filesize:
                content = f.read(1024)
                sk.send(content)
                filesize -= len(content)
    elif num == "2":
        pass
    

      b : 版本二: 大文件的传输:

      服务器端的代码:

    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()
    

      客户端的代码:

    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
    

      c : 版本三 : 小文件的传输

      服务器端的代码:

    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()
    

      客户端的代码:

    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
    

    3 . 切换目录

    用户输入一个绝对路径, 以此路径为基础(此时服务器应该返回这个目录下的所有文件及文件夹)
    如果用户继续输入..服务器要返回上一层的所有文件及文件夹
    如果用户输入的是cd
    后边一定要求用户继续输入一个当前目录下的文件夹的名字.此时
    服务器需要给用户返回该文件夹下的所有文件及文件夹
    

      服务器端代码:

    import socket
    import os
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9080))
    sk.listen()
    conn, addr = sk.accept()
    abs_path = conn.recv(1024).decode('utf-8')
    dir = os.listdir(abs_path)
    str = '--'.join(dir)
    conn.send(str.encode('utf-8'))
    while 1:
        cmd = conn.recv(1024).decode('utf-8')
        if cmd == '..':
    
            file_path = os.path.dirname(abs_path)
            dir = os.listdir(file_path)
            str = '--'.join(dir)
            abs_path = file_path
            conn.send(str.encode('utf-8'))
        else:
            print(cmd)
            file_name = cmd.split(':')[1]
            current_path = abs_path +'/' +file_name
            if os.path.isdir(current_path):
                file_lst = os.listdir(current_path)
                flie_str = '--'.join(file_lst)
                abs_path = current_path
                conn.send(flie_str.encode('utf-8'))
            else:
                conn.send(r'bushiwenjian')
    
    conn.close()
    sk.close()

      客户端代码: 

    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',9080))
    abs_path = input('请输入一个绝对路径:')
    sk.send(abs_path.encode('utf-8'))
    str = sk.recv(1024).decode('utf-8')
    dir = str.split('--')
    print(dir)
    while 1:
        cmd = input('请用户输入命令:')
        if cmd == '..':
            sk.send(cmd.encode('utf-8'))
            str = sk.recv(1024).decode('utf-8')
            dir = str.split('--')
            print(dir)
        if cmd == 'cd':
            file_name = input('请用户输入一个文件夹的名字>>>')
            sk.send((cmd + ':'+file_name).encode('utf-8'))
            current_dir = sk.recv(1024).decode('utf-8')
            print(current_dir.split('--'))
    
    sk.close()
    

      

     

  • 相关阅读:
    开启防火墙如何部署k8s
    docker及k8s安装consul
    docker安装rocketmq
    docker安装gitlab
    k8s认证与授权
    部署dashboard
    k8sStatefulSet控制器
    k8sSecret资源
    k8sConfigMap资源
    使用nfs制作动态分配存储卷
  • 原文地址:https://www.cnblogs.com/gyh412724/p/9488432.html
Copyright © 2011-2022 走看看