一,粘包现象
1.合包机制:
数据长度很短,包与包之间的间隔短
2.拆包机制:
大数据会发生拆分
不会一次性的全部发生到对方
对方在接收的时候很可能没有办法一次性接收到所有的信息
那么没有接收完的信息很可能和后面的信息粘在一起
3.粘包现象只发生在tcp协议
tcp协议的传输是流式传输
每一条消息与信息之间是没有边界
4.udp协议中不会发生粘包现象的
适合短数据的发生
不建议你发送过长的数据
发生过长的数据会增大你数据丢失的几率
二,粘包现象总结:
在程序中会出现粘包:
收发数据的边界不清晰
接收数据这一端不知道要接收数据的长度到底有多少
三,解决粘包现象的方法:
解决方案1:
自定义协议,根据接收的长度控制
弊端:
复杂
最多只能一次传递9999个字节
#server端 import socket sk = socket.socket() sk.bind(('127.0.0.1',9090)) sk.listen() conn,addr = sk.accept() s = input('>>>') # 'a'*20 str(len(s)) # '20' str(len(s)).zfill(4)+str(len(s)) #client端 import socket sk = socket.socket() sk.connect(('127.0.0.1',9090)) ret1 = sk.recv(4) num1 = int(ret1.decode('utf-8')) ret = sk.recv(num1) print(ret) ret2 = sk.recv(4) num2 = int(ret2.decode('utf-8')) ret = sk.recv(num2) print(ret) sk.close()
解决方案2:
struct模块能够把不管多长的数据都转换成一个4位的字节
#server端 import struct import socket sk = socket.socket() sk.bind(('127.0.0.1',9090)) sk.listen() conn,addr = sk.accept() while True: s = input('>>>').encode('utf-8') pack_num = struct.pack('i',len(s)) #‘i’指定int数据类型 conn.send(pack_num) conn.send(s) conn.close() sk.close() #client端 import socket import struct sk = socket.socket() sk.connect(('127.0.0.1',9090)) while True: pack_num = sk.recv(4) num = struct.unpack('i',pack_num)[0] ret = sk.recv(num) print(ret.decode('utf-8')) sk.close()
四,自定义协议的作用
# 统计数据的长度 # 通过struct模块,处理这个长度 # 得到一个4个字节的结果 # 先发送4个字节的长度 # 再发送数据 #10240/20480 # 另一端先接收4个四个字节 # 通过strut来处理这四个字节,拿到数据的长度 # 安照数据的长度来接收