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'"K\x08\x00' 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 S14\day32\实现大文件的传输\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

猜你喜欢

转载自www.cnblogs.com/fengxb1213/p/12512052.html
今日推荐