Python各协议下socket黏包问题原理


Posted in Python onApril 12, 2022

1.socket黏包问题原理

黏包:指数据与数据之间没有明确的分界线,导致不能正确的读取数据。

应用数据想要发送数据就必须将数据交给操作系统,而操作系统需要同时为所有的应用程序提供数据传输服务,就意味着不可能马上将应用数据发送,就需要为程序提供一个缓冲区,用于临时存放数据。

当发送数据很快,有两条数据都在缓冲区时,操作系统可能将两个数据发给接收方,数据之间没有分界线,接收方会误认为是一条数据。

2.UDP协议

UDP在收发数据时是基于数据包的,即一个包一个包的发送,包与包之间有明确的分界,到达对方缓冲区后也是独立数据包。这种方式存在的问题:

①发送数据的长度每个操作系统会有不同的限制,数据超过限制则无法发送;

②接收方接收数据时,如果应用程序提供的缓存容量小于数据包的长度,则会造成数据的丢失,而缓冲区大小不可能无限大。

这意味着UDP不会出现黏包问题,但会丢失数据,不可靠。

3.TCP协议

TCP增加了一套校验规则来保证数据的完整性,会将超过TCP包最大长度的数据拆分为多个TCP包,并在传输数据时为每一个TCP数据包指定一个顺序号,接收方在收到TCP数据包后按照顺序将数据包进行重组,重组后的数据全都是二进制数据,且每次收到的二进制数据之间没有明显的分界。基于这种工作机制,TCP在三种情况下发生黏包问题:

①当单个数据包较小时,接收方可能一次性读取了多个包的数据;

②当整体数据较大时,接收方可能一次性仅读取了一个包的一部分内容;

③另外TCP协议为提高效率,增加了一种优化机制,会将数据小且发送间隔短的数据合并发送,该机制也会导致发送方将两个数据包粘在一起发送。

也就是说,TCP传输数据是可靠的,但是会黏包。

4.发送方出现的黏包

服务器端:

from socket import *
server_socket = socket(AF_INET,SOCK_STREAM)
server_socket.bind(('',8080))
server_socket.listen(5)
 
new_socket,client_addr = server_socket.accept()
 
data1 = new_socket.recv(1024)
data2 = new_socket.recv(1024)
print("收到的第一条数据:",data1)
print("收到的第二条数据:",data2)
 
new_socket.close()
server_socket.close()

客户端:

from socket import *
 
client_socket = socket(AF_INET,SOCK_STREAM)
client_socket.connect(('10.175.193.126',8080))
client_socket.send('hello'.encode('utf-8'))
client_socket.send('word'.encode('utf-8'))
client_socket.close()

服务器端接收到的数据:

Python各协议下socket黏包问题原理

由于客户端两条数据发送间隔太短且数据包太小,被服务器端误认为是一条数据。

5. 接收方出现的黏包

服务器端:

from socket import *
import time
 
server_socket = socket(AF_INET,SOCK_STREAM)
server_socket.bind(('',8080))
server_socket.listen(5)
 
new_socket,client_addr = server_socket.accept()
print("连接成功!",client_addr)
 
data1 = new_socket.recv(3) #每次只接收三个字节,接收不完整
time.sleep(6)
print("收到的第一条数据:",data1)
 
data2 = new_socket.recv(10)
#接收第一次未接收的数据,若有空间,会继续接收新数据
print("收到的第二条数据:",data2)
 
new_socket.close()
server_socket.close()

客户端:

from socket import *
#通过time模块使客户端发送多个数据包时,时间间隔变长
import time
 
client_socket = socket(AF_INET,SOCK_STREAM)
client_socket.connect(('10.175.193.126',8080))
client_socket.send('hello'.encode('utf-8'))
time.sleep(5) #让当前线程休眠5秒
client_socket.send('word'.encode('utf-8'))
 
client_socket.close()

服务器端接收到的数据:

Python各协议下socket黏包问题原理

6.黏包的成因

①服务器端出现黏包:接收方不知道消息之间的界限,不知道一个消息要提取多少字节的数据造成的;

②客户端出现黏包:TCP在发送数据少且间隔时间短的数据包时,会将几条合并一起发送。

到此这篇关于Python数据传输黏包问题的文章就介绍到这了!

Python 相关文章推荐
Python中单、双下划线的区别总结
Dec 01 Python
TensorFlow深度学习之卷积神经网络CNN
Mar 09 Python
python机器学习之贝叶斯分类
Mar 26 Python
如何安装多版本python python2和python3共存以及pip共存
Sep 18 Python
Scrapy框架使用的基本知识
Oct 21 Python
selenium+python自动化测试之多窗口切换
Jan 23 Python
pandas DataFrame的修改方法(值、列、索引)
Aug 02 Python
python3使用GUI统计代码量
Sep 18 Python
Django框架HttpResponse对象用法实例分析
Nov 01 Python
Python+appium框架原生代码实现App自动化测试详解
Mar 06 Python
python中字典增加和删除使用方法
Sep 30 Python
MATLAB 如何求取离散点的曲率最大值
Apr 16 Python
Python爬虫网络请求之代理服务器和动态Cookies
Apr 12 #Python
分享Python异步爬取知乎热榜
尝试使用Python爬取城市租房信息
Apr 12 #Python
Python采集爬取京东商品信息和评论并存入MySQL
Apr 12 #Python
Python实现批量将文件复制到新的目录中再修改名称
Python多线程实用方法以及共享变量资源竞争问题
Apr 12 #Python
Python使用socket去实现TCP客户端和TCP服务端
Apr 12 #Python
You might like
模仿OSO的论坛(三)
2006/10/09 PHP
php mssql 时间格式问题
2009/01/13 PHP
PHP 编写大型网站问题集
2010/05/07 PHP
完美的2个php检测字符串是否是utf-8编码函数分享
2014/07/28 PHP
php输入数据统一类实例
2015/02/23 PHP
php添加数据到xml文件的简单例子
2016/09/08 PHP
php+ajax实现商品对比功能示例
2019/04/13 PHP
自己做的模拟模态对话框实现代码
2012/05/23 Javascript
jQuery Tools tab使用介绍
2012/07/14 Javascript
使用jquery的ajax需要注意的地方dataType的设置
2013/08/12 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/20 Javascript
JS去掉第一个字符和最后一个字符的实现代码
2014/02/20 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
2014/12/20 Javascript
jQuery()方法的第二个参数详解
2015/04/29 Javascript
javascript实现鼠标放上后下边对应内容变换的效果
2015/08/06 Javascript
node.js下LDAP查询实例分享
2015/09/30 Javascript
jquery获取select选中值的方法分析
2015/12/22 Javascript
jQuery easyui的validatebox校验规则扩展及easyui校验框validatebox用法
2016/01/18 Javascript
Ionic如何实现下拉刷新与上拉加载功能
2016/06/03 Javascript
jQuery插件HighCharts实现的2D条状图效果示例【附demo源码下载】
2017/03/15 Javascript
微信小程序引用公共js里的方法的实例详解
2017/08/17 Javascript
浅谈vue中数据双向绑定的实现原理
2017/09/14 Javascript
vue基于Element构建自定义树的示例代码
2017/09/19 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
Python字符串转换成浮点数函数分享
2015/07/24 Python
Python 文件操作的详解及实例
2017/09/18 Python
django orm 通过related_name反向查询的方法
2018/12/15 Python
Django 解决distinct无法去除重复数据的问题
2020/05/20 Python
Keras 在fit_generator训练方式中加入图像random_crop操作
2020/07/03 Python
优秀学生干部个人的自我评价
2013/10/04 职场文书
一年级班主任寄语
2014/01/19 职场文书
美容院店长岗位职责
2014/04/08 职场文书
城市轨道交通工程职业生涯规划书范文
2014/09/16 职场文书
Nginx配置80端口访问8080及项目名地址方法解析
2021/03/31 Servers
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
5人制售《绝地求生》游戏外挂获利500多万元 被判刑
2022/03/31 其他游戏