Python:粘包问题
粘包现象
1 、tcp有粘包及udp无粘包
- TCP 是面向连接的,面向流的可靠协议;发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,
合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制面向流的通信是无消息保护边界的。 - UDP(用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来
记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。
注:tcp是基于数据流的,于是收发的消息不能为空,这就需要在客户端和服务端都添加空消息的处理机制,防止程序卡住,
而udp是基于数据报的,即便是你输入的是空内容(直接回车),那也不是空消息,udp协议会帮你封装上消息头
2 、产生原因:
1、接收端不知道消息的界限,不知道一次提取多少字节数据
2、TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,
通常TCP会根据优化算法(Nagle算法)把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据
产生粘包场景:(1)发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
(2)接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
3 、解决方案
为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
struct 模块
注:struct 模块 把一个数字类型转化为固定长度的bytes
(struct.pack)打包 (struct.unpack)解包
res=(struct.pack('i',4855524)) #b'\x04\xe6\xe4\x02' 打包
print(res)
print(struct .unpack('i',res)[0]) #解包
服务端:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import subprocess
import socket
import struct
import json
phone= socket.socket(socket.AF_INET ,socket.SOCK_STREAM )
phone.bind(('127.0.0.1',8080))
phone.listen(5)
while True :conn,client=phone.accept()while True :try:cmd = conn.recv(1024)if len(cmd) == 0: break# 远程执行命令obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, # 解码stdout=subprocess.PIPE, # 正确信息stderr=subprocess.PIPE # 错误信息)stdout = obj.stdout.read()stderr = obj.stderr.read()#先制作报头head_dic= {'filename':'a.txt','total_size':len(stdout)+len(stderr),'hash':'asdf165485221'}head_json = json.dumps(head_dic)head_bytes= head_json.encode('utf-8')#1、先把报头的长度打包成四个bytes,然后发送conn.send(struct.pack('i',len(head_bytes)))#2、发送报头conn.send(head_bytes)#3、发送真实数据conn.send(stdout )conn.send(stderr)except ConnectionResetError:breakconn.close()phone.close()
客户端:
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import struct
import socket
import json
phone= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone. connect(('127.0.0.1',8080))
while True :msg = input('<<<')if msg == 0:continue#phone.send(msg.encode('utf-8'))phone.send(bytes(msg,encoding='utf-8'))#1、先收4个字节,该4个字节包含报头的长度 解包header_len=struct .unpack('i',phone.recv(4))[0]#2、通过报头长度,再接受报头内容header_bytes=phone.recv(header_len) #通过报头长度,拿到bytes内容#从报头中解析出想要的内容header_json=header_bytes .decode('utf-8') #报头内容解码得到字符串类型header_dic=json .loads(header_json) #反序列化得到字典print(header_dic)total_size = header_dic['total_size']#3、再收真实的数据recv_size =0 #初始值长度res=b'' #接收的具体值while recv_size< total_size:data= phone.recv(1024)res+=data # 拼接具体的值recv_size += len(data) #累加长度print(res.decode('gbk')) #收到的信息用GBK解码
phone.close()
Python:粘包问题相关推荐
- python socket实现文件传输(防粘包)
1.文件传输的要点: 采用iterator(迭代器对象)迭代读取,提高读取以及存取效率: 通过for line in file_handles逐行conn.send(): 2.socket粘包问题: ...
- 学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本
立即学习:https://edu.csdn.net/course/play/24458/296243?utm_source=blogtoedu 粘包现象的解决:简单版 1.思路: 在服务器 ...
- 学习笔记(10):Python网络编程并发编程-粘包现象
立即学习:https://edu.csdn.net/course/play/24458/296240?utm_source=blogtoedu 粘包现象:服务器接收到客户端的命令后,进行执行得到结果后 ...
- python D28 粘包
一.两种粘包: MTU简单解释: MTU是Maximum Transmission Unit的缩写.意思是网络上传送的最大数据包.MTU的单位是字节. 大部分网络设备的MTU都是1500个字节,也就是 ...
- python/socket编程之粘包
python/socket编程之粘包 粘包 只有TCP有粘包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 发 ...
- 完美解决Python套接字编程时TCP断包与粘包问题
首先,来看一个代码,使用TCP协议,发送端发送一句话,接收端接收并显示,运行完全正常. 接下来,把客户端代码稍微修改一下,连续发送多个数据, 按照正常的想法,在服务端输出的信息应该是分为多行的,这样才 ...
- python串口数据分包_python TCP Socket的粘包和分包的处理详解
概述 在进行TCP Socket开发时,都需要处理数据包粘包和分包的情况.本文详细讲解解决该问题的步骤.使用的语言是Python.实际上解决该问题很简单,在应用层下,定义一个协议:消息头部+消息长度+ ...
- Python网络与并发编程 02 TCP粘包
TCP/Socket与subprocess 我们准备做一个可以在Client端远程执行Server端的shell命令并拿到其执行结果的程序,而涉及到网络通信就必然会使用到socket模块,此外还需要s ...
- 小白IT:Python中的网络编程是什么样?如何传输?三次捂手四次挥手?什么又是粘包呢
文章目录 Python 基础---网络编程 一 前引 二.软件开发的架构 1.C/S架构 2.B/S架构 三.网络通信原理* 1.前引 2.互联网的本质:一系列的网络协议 结论 3.osi七层协议** ...
最新文章
- 工程大小优化之图片资源
- php-fpm定义成集群资源时报错解决方法
- Focal Loss改进版 GFocal Loss
- C# 集合交、并、差、去重,对象集合交并差
- CvSVM::EPS_SVR train_auto assertion sv_count != 0 failed原因
- C++中输入输出的十六进制八进制
- 周五话分析 | 方法论难落地?来个量身定制版本吧(AARRR模型)
- 倚天遇到屠龙:LightGBM VS xgboost谁才是最强的梯度提升库?
- matlab disteclud,机器学习实战ByMatlab(四)二分K-means算法
- eclipse里的无参构造_构造方法及其作用
- 知乎超高赞:都有哪些习惯值得长期坚持?
- 将两大小完全相同的照片进行加权混合对比
- 并发容器——ConcurrentHashMap
- 匹配IP的正则表达式
- 蓝桥杯 ALGO-21算法训练 装箱问题(动态规划,01背包)
- c语言ch能储存多少字符,二级c语言程序设计习题与解答ch5-7函数字符(11页)-原创力文档...
- ubuntu20.04 显卡驱动 cuda cudnn安装
- yml在线格式转换工具
- Iptable与firewalld防火墙
- 基于Redisson实现的延时队列RedissonDelayedQueue实现websocket服务端心跳监听