• python学习Day32--大文件传输+目录切换


    一、回顾

    1、粘包:tcp协议粘包,udp协议不粘包

      ① 合包机制(nagle算法)和拆包机制 ——发生在发送端

    2、subprocess.Popen()  执行系统命令

    3、面试题:

      ① a=1  b=2  两个数互换你有几个方法?

     1 a=1
     2 b=2
     3 
     4 # 第一种方法: 不借助第三个变量
     5 a,b=b,a
     6 print(a,b)  # 2,1
     7 
     8 # 第二种方法: 借助第三个变量
     9 c = a
    10 a = b
    11 b = c
    12 print(a,b)  # 1,2  (这里因为上面a,b已经互换)
    13 #
    14 # # 第三种方法:不借助第三个变量
    15 a = a+b
    16 b = a-b
    17 a = a-b
    18 print(a,b) # 2,1

      ② tcp协议为什么比udp协议更可靠?

      tcp是面向连接的,而udp是面向无连接的

      tcp通信过程中有一个ACK,确认收到消息的一个标识

    二、大文件传输

     1、如何把字典长度+字典内容一起发送而分别读出长度和内容?

      字典的长度是不固定的,因此接收的数据大小也就不固定。如果将字典的长度(无论多大)都转化成4个字节的长度,那么接收的数据也就固定了。实现如下:(学习新的模块:struct——struct.pack(type,num))

    1 # *******************转换成4个字节长度**********************开始
    2 import struct
    3 
    4 a = 543522
    5 
    6 s = struct.pack('i',a)
    7 print(s,len(s))  # b'"Kx08x00' 4
    8 print(struct.unpack('i',s))  # (543522,)
    9 # *******************转换成4个字节长度**********************结束

    2、大文件传输版本

     1 # *******************服务端**********************开始
     2 import socket
     3 import json
     4 import struct
     5 
     6 sk = socket.socket()
     7 sk.bind(("127.0.0.1",8001))
     8 sk.listen()
     9 conn,addr = sk.accept()
    10 b_len_dic = conn.recv(4)
    11 len_dic = struct.unpack('i',b_len_dic)[0]# 获取到int类型字典的长度,
    12 # unpack得到的是一个元组,要取下标为0的位置
    13 str_dic = conn.recv(len_dic).decode('utf-8')
    14 # str_dic = {"opt":menu.get(num),"filename":None,"filesize":None}
    15 dic = json.loads(str_dic)
    16 if dic["opt"] == "upload":
    17     filename = "1"+ dic["filename"]
    18     with open(filename,"ab") as f:
    19         while dic['filesize']:
    20             content = conn.recv(1024)
    21             f.write(content)
    22             dic['filesize'] -= len(content)
    23 
    24 elif dic["opt"] == "download":
    25     # 客户端发来一个字典要执行的功能,以及客户端自己的绝对路径
    26     # 服务器要返回这个绝对路径中所有文件及文件夹
    27     # 客户端自己选择进入到哪一层目录下
    28     # 服务器都要返回对应目录下所有文件及文件夹
    29     # 客户随时选择某一个目录下的某一个文件进行下载
    30 
    31 
    32     # 客户端发送来一个字典,包含了要进行的操作,要下载的文件的绝对路径,
    33     # 根据绝对路径去读取文件内容
    34     # 一边读,一遍发
    35     pass
    36 
    37 conn.close()
    38 sk.close()
    39 # *******************服务端**********************结束
    大文件传输--服务端
     1 # *******************客服端**********************开始
     2 import socket
     3 import os
     4 import json
     5 import struct
     6 
     7 sk = socket.socket()
     8 sk.connect(("127.0.0.1",8001))
     9 menu = {"1":"upload","2":"download"}
    10 for k,v in menu.items():
    11     print(k,v)
    12 num = input("请输入功能选项:")
    13 if num == "1":
    14     dic = {"opt":menu.get(num),"filename":None,"filesize":None}
    15     file_path = input("请输入一个绝对路径:")# 文件的绝对路径
    16     # E:Python S14day32实现大文件的传输11.mp4
    17     filename = os.path.basename(file_path)# 文件名字
    18     filesize = os.path.getsize(file_path)# 获取用户输入的路径中文件的大小
    19     dic["filename"] = filename
    20     dic["filesize"] = filesize
    21     str_dic = json.dumps(dic)
    22     len_dic = len(str_dic)# 获取到字典的长度,是一个int类型的数据   46   146
    23     b_len_dic = struct.pack('i',len_dic)# 用一个4bytes的数据表示字典的长度
    24 
    25     sk.send(b_len_dic + str_dic.encode("utf-8"))# 将bytes类型的字典的长度 + bytes类型的字典的内容,一起发送给服务器
    26 
    27 
    28     #  因为上边send字典时,如果程序执行过快,可能会马上执行到下边的send(content)
    29     #  此时有可能会发生粘包,所以在此中间加一个recv,为了避免粘包
    30     with open(file_path,"rb") as f:
    31         while filesize:
    32             content = f.read(1024)
    33             sk.send(content)
    34             filesize -= len(content)
    35 
    36 elif num == "2":
    37     pass
    38 # *******************客服端**********************结束
    大文件传输--客服端

    3、目录切换

     1 # *******************服务端**********************开始
     2 import socket
     3 import os
     4 
     5 sk = socket.socket()
     6 sk.bind(('127.0.0.1',8888))
     7 sk.listen()
     8 
     9 conn,addr = sk.accept()
    10 
    11 abs_path = conn.recv(1024).decode('utf-8')
    12 
    13 def send_data(conn,path):
    14     # 给一个目录绝对地址,我把目录发给客户端
    15     lst_dir = os.listdir(path) # 获取到该文件下所有文件的列表
    16     str_dir = '--'.join(lst_dir) # 用--连接成一个字符串
    17     conn.send(str_dir.encode('utf-8'))
    18 
    19 current_dir = abs_path+'/'
    20 send_data(conn,current_dir)
    21 
    22 while 1:
    23     cmd = conn.recv(1024).decode('utf-8')
    24     if cmd == '..':
    25         current_dir = current_dir.split('/')[:-1] # 原本后面有一个空,切片就没有了
    26         current_dir.pop()
    27         current_dir = '/'.join(current_dir)+'/'
    28         # current_dir = os.path.dirname(current_dir)
    29         # 上面是得到上一级路径,注意区分basename(path)
    30         if current_dir == '/':
    31             conn.send("没有上一级了".encode('utf-8'))
    32         else:
    33             send_data(conn,current_dir)
    34     else:
    35         filename = cmd.split(' ')[1]
    36         current_dir += filename+'/'
    37         if os.path.isdir(current_dir):
    38             send_data(conn,current_dir)
    39         else:
    40             conn.send('不是文件'.encode('utf-8'))
    41 
    42 conn.close()
    43 sk.close()
    44 # *******************服务端**********************结束
    服务端
     1 # *******************客户端**********************开始
     2 import socket
     3 import os
     4 
     5 sk = socket.socket()
     6 sk.connect_ex(('127.0.0.1',8888))
     7 
     8 abs_path = input("请输入你的根目录:")
     9 sk.send(abs_path.encode('utf-8'))
    10 current_dir = sk.recv(1024).decode('utf-8')
    11 print(current_dir.split('--'))
    12 
    13 while 1:
    14     cmd = input("请输入>>>")
    15     if cmd == '..':
    16         sk.send(cmd.encode('utf-8'))
    17         current_dir = sk.recv(1024).decode('utf-8')
    18         print(current_dir.split('--'))
    19     if cmd == 'cd':
    20         filename = input("请输入一个人文件夹名:")
    21         sk.send((cmd+' '+filename).encode('utf-8'))
    22         current_dir = sk.recv(1024).decode('utf-8')
    23         print(current_dir.split('--'))
    24 
    25 sk.close()
    26 # *******************客户端**********************结束
    客户端

    时间:2020-03-18   00:39:20

    作者(QQ):931935931

  • 相关阅读:
    js变量如何赋值给css使用?
    前端预览与下载PDF小结
    子组件如何改父组件传过来的值
    TensorRT转换时的静态模式与动态模式
    Linux:搭建GlusterFS文件系统
    OpenFeign传输文件MultipartFile
    Docker:commit、export、import、save、load命令的使用
    Git:代码版本回退
    docker安装Drools Workbench
    ArchLinux:Typora设置gitee图床
  • 原文地址:https://www.cnblogs.com/fengxb1213/p/12512052.html
Copyright © 2020-2023  润新知