一、回顾
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、大文件传输版本
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 # *******************服务端**********************结束
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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、目录切换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 # *******************服务端**********************结束
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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