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中文件遍历的两种方法
Jun 16 Python
python获取文件扩展名的方法
Jul 06 Python
socket + select 完成伪并发操作的实例
Aug 15 Python
Python标准库之itertools库的使用方法
Sep 07 Python
python实现Adapter模式实例代码
Feb 09 Python
30秒轻松实现TensorFlow物体检测
Mar 14 Python
Python3.x爬虫下载网页图片的实例讲解
May 22 Python
浅谈Pandas:Series和DataFrame间的算术元素
Dec 22 Python
python二进制读写及特殊码同步实现详解
Oct 11 Python
tensorflow2.0保存和恢复模型3种方法
Feb 03 Python
TensorBoard 计算图的可视化实现
Feb 15 Python
利用pandas向一个csv文件追加写入数据的实现示例
Apr 23 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
php通过隐藏表单控件获取到前两个页面的url
2014/09/09 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
kmock javascript 单元测试代码
2011/02/06 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
2013/08/11 Javascript
浅析jQuery中调用ajax方法时在不同浏览器中遇到的问题
2014/06/11 Javascript
JavaScript中定义函数的三种方法
2015/03/12 Javascript
Javascript实现获取及设置光标位置的方法
2015/07/21 Javascript
JavaScript 常见安全漏洞和自动化检测技术
2015/08/21 Javascript
如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)
2015/10/29 Javascript
详解javascript的变量与标识符
2016/01/04 Javascript
讲解JavaScript的Backbone.js框架的MVC结构设计理念
2016/02/14 Javascript
浅谈JavaScript 数据属性和访问器属性
2016/09/01 Javascript
基于代数方程库Algebra.js解二元一次方程功能示例
2017/06/09 Javascript
js+springMVC 提交数组数据到后台的实例
2019/09/21 Javascript
[06:20]2015国际邀请赛第三日top10
2015/08/08 DOTA
[58:58]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第二场
2018/04/05 DOTA
python创建文件备份的脚本
2018/09/11 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
python 3.7.4 安装 opencv的教程
2019/10/10 Python
Python 自由定制表格的实现示例
2020/03/20 Python
next在python中返回迭代器的实例方法
2020/12/15 Python
HTML5 MiranaVideo播放器 (代码开源)
2010/06/11 HTML / CSS
联想加拿大官方网站:Lenovo Canada
2018/04/05 全球购物
Wojas罗马尼亚网站:波兰皮鞋品牌
2018/11/01 全球购物
德国的大型美妆个护电商:Flaconi
2020/06/26 全球购物
linux面试题参考答案(7)
2014/07/24 面试题
Ajxa常见问题都有哪些
2014/03/26 面试题
领导班子四风对照检查材料思想汇报
2014/09/26 职场文书
部门主管竞聘书
2015/09/15 职场文书
领导莅临指导欢迎词
2015/09/30 职场文书
争做文明公民倡议书
2019/06/24 职场文书
Python中相见恨晚的技巧
2021/04/13 Python
Nginx+Tomcat负载均衡集群的实现示例
2021/10/24 Servers
WebWorker 封装 JavaScript 沙箱详情
2021/11/02 Javascript
【海涛DOTA解说】EVE女子战队独家录像加ZSMJ神牛两连发
2022/04/01 DOTA
Win11运行育碧游戏总是崩溃怎么办 win11玩育碧游戏出现性能崩溃的解决办法
2022/04/06 数码科技