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中关于时间和日期函数的常用计算总结(time和datatime)
Mar 08 Python
python安装以及IDE的配置教程
Apr 29 Python
python fabric使用笔记
May 09 Python
Windows下为Python安装Matplotlib模块
Nov 06 Python
简单实现python画圆功能
Jan 25 Python
Django项目中model的数据处理以及页面交互方法
May 30 Python
python 接口实现 供第三方调用的例子
Aug 13 Python
Python 用三行代码提取PDF表格数据
Oct 13 Python
pygame实现贪吃蛇游戏(下)
Oct 29 Python
Python开发.exe小工具的详细步骤
Jan 27 Python
python字符串拼接.join()和拆分.split()详解
Nov 23 Python
分享3个非常实用的 Python 模块
Mar 03 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中的动态调用实例分析
2015/01/07 PHP
PHP rsa加密解密使用方法
2015/04/27 PHP
yii2实现根据时间搜索的方法
2016/05/25 PHP
JQuery jsonp 使用示例代码
2009/08/12 Javascript
JQuery与JSon实现的无刷新分页代码
2011/09/13 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
jquery实现通用的内容渐显Tab选项卡效果
2015/09/07 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
2017/01/20 Javascript
详解angular中通过$location获取路径(参数)的写法
2017/03/21 Javascript
jQuery.form.js的使用详解
2017/06/14 jQuery
Three.js利用dat.GUI如何简化试验流程详解
2017/09/26 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
2018/03/12 Javascript
vue中设置height:100%无效的问题及解决方法
2018/07/27 Javascript
使用vue点击li,获取当前点击li父辈元素的属性值方法
2018/09/12 Javascript
Vue.js的复用组件开发流程完整记录
2018/11/29 Javascript
vue实现歌手列表字母排序下拉滚动条侧栏排序实时更新
2019/05/14 Javascript
微信小程序开发打开另一个小程序的实现方法
2020/05/17 Javascript
[06:45]2018DOTA2亚洲邀请赛 4.5 SOLO赛 Sccc vs Maybe
2018/04/06 DOTA
python实现颜色rgb和hex相互转换的函数
2015/03/19 Python
Python实现微信公众平台自定义菜单实例
2015/03/20 Python
让python在hadoop上跑起来
2016/01/27 Python
浅谈Pandas 排序之后索引的问题
2018/06/07 Python
Python父目录、子目录的相互调用方法
2019/02/16 Python
简单了解python的内存管理机制
2019/07/08 Python
Django中使用session保持用户登陆连接的例子
2019/08/06 Python
什么是python的函数体
2020/06/19 Python
澳大利亚体育和露营装备在线/实体零售商:Find Sports
2020/06/03 全球购物
教师实习自我鉴定
2013/12/11 职场文书
物业管理毕业生的自我评价
2014/02/17 职场文书
土建专业大学生自荐信范文
2014/04/09 职场文书
作风建设年活动总结
2014/08/27 职场文书
大学生见习总结报告
2015/06/24 职场文书
会议承办单位欢迎词
2019/07/09 职场文书
签证扫盲贴,41个常见签证知识,需要的拿走
2019/08/09 职场文书
大学生党员暑假实践(活动总结)
2019/08/21 职场文书
Python中的tkinter库简单案例详解
2022/01/22 Python