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中os.path用法分析
Jan 15 Python
使用python实现生成用户信息
Mar 20 Python
Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果示例
Jan 29 Python
浅谈配置OpenCV3 + Python3的简易方法(macOS)
Apr 02 Python
解决webdriver.Chrome()报错:Message:'chromedriver' executable needs to be in Path
Jun 12 Python
django 做 migrate 时 表已存在的处理方法
Aug 31 Python
python conda操作方法
Sep 11 Python
Python操作Sonqube API获取检测结果并打印过程解析
Nov 27 Python
详解python 破解网站反爬虫的两种简单方法
Feb 09 Python
PyTorch中torch.tensor与torch.Tensor的区别详解
May 18 Python
Python如何使用ElementTree解析xml
Oct 12 Python
5 分钟读懂Python 中的 Hook 钩子函数
Dec 09 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
mysql 全文搜索 技巧
2007/04/27 PHP
php实现TCP端口检测的方法
2015/04/01 PHP
thinkPHP+PHPExcel实现读取文件日期的方法(含时分秒)
2016/07/07 PHP
微信小程序 消息推送php服务器验证实例详解
2017/03/30 PHP
js将json格式内容转换成对象的方法
2013/11/01 Javascript
js和css写一个可以自动隐藏的悬浮框
2014/03/05 Javascript
json的定义、标准格式及json字符串检验
2014/05/11 Javascript
简单讲解jQuery中的子元素过滤选择器
2016/04/18 Javascript
学做Bootstrap的第一个页面
2016/05/15 HTML / CSS
BootStrap智能表单实战系列(六)表单编辑页面的数据绑定
2016/06/13 Javascript
ui组件之input多选下拉实现方法(带有搜索功能)
2016/07/14 Javascript
纯js三维数组实现三级联动效果
2017/02/07 Javascript
Vue 单文件中的数据传递示例
2017/03/21 Javascript
基于react框架使用的一些细节要点的思考
2017/05/31 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
node.js遍历目录的方法示例
2018/08/01 Javascript
jQuery使用bind动态绑定事件无效的处理方法
2018/12/11 jQuery
layer.js之回调销毁对话框的例子
2019/09/11 Javascript
Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例
2020/11/18 Vue.js
[03:51]吞吞映像 每周精彩击杀top10第二弹
2014/06/25 DOTA
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
Python从文件中读取数据的方法讲解
2019/02/14 Python
Python使用Pickle模块进行数据保存和读取的讲解
2019/04/09 Python
python os.fork() 循环输出方法
2019/08/08 Python
在Pytorch中计算卷积方法的区别详解(conv2d的区别)
2020/01/03 Python
浅谈Python3多线程之间的执行顺序问题
2020/05/02 Python
使用CSS媒体查询(Media Queries)和JavaScript判断浏览器设备类型的方法
2014/04/03 HTML / CSS
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
出纳员岗位职责风险
2014/03/06 职场文书
个人整改措施书面材料
2014/10/24 职场文书
兴趣班停课通知
2015/04/24 职场文书
法律意见书范文
2015/05/20 职场文书
北京青年观后感
2015/06/15 职场文书
2016年敬老月活动总结
2016/04/05 职场文书
Golang 正则匹配效率详解
2021/04/25 Golang
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
2021/06/23 Python