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实现的数据结构与算法之队列详解
Apr 22 Python
浅谈python字典多键值及重复键值的使用
Nov 04 Python
Python处理文本文件中控制字符的方法
Feb 07 Python
python中验证码连通域分割的方法详解
Jun 04 Python
Python中的groupby分组功能的实例代码
Jul 11 Python
Python3匿名函数lambda介绍与使用示例
May 18 Python
用Python获取摄像头并实时控制人脸的实现示例
Jul 11 Python
在pycharm下设置自己的个性模版方法
Jul 15 Python
Python 可变类型和不可变类型及引用过程解析
Sep 27 Python
Python小白不正确的使用类变量实例
May 29 Python
TensorFlow的环境配置与安装教程详解(win10+GeForce GTX1060+CUDA 9.0+cuDNN7.3+tensorflow-gpu 1.12.0+python3.5.5)
Jun 22 Python
Python同时处理多个异常的方法
Jul 28 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中error_reporting()函数的用法(修改PHP屏蔽错误)
2011/07/01 PHP
PHP中仿制 ecshop验证码实例
2017/01/06 PHP
centos7上编译安装php7以php-fpm方式连接apache
2018/11/08 PHP
Thinkphp 框架扩展之驱动扩展实例分析
2020/04/27 PHP
JObj预览一个JS的框架
2008/03/13 Javascript
JQuery1.6 使用方法三
2011/11/23 Javascript
仅IE支持clearAttributes/mergeAttributes方法使用介绍
2012/05/04 Javascript
ParseInt函数参数设置介绍
2014/01/02 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
JS实现的论坛Ajax打分效果完整实例
2015/10/31 Javascript
JavaScript对象参数的引用传递
2016/01/14 Javascript
浅析jQuery Ajax请求参数和返回数据的处理
2016/02/24 Javascript
JavaScript比较两个数组的内容是否相同(推荐)
2017/05/02 Javascript
详解HTTPS 的原理和 NodeJS 的实现
2017/07/04 NodeJs
Js利用Canvas实现图片压缩功能
2017/09/13 Javascript
Angular @HostBinding()和@HostListener()用法
2018/03/05 Javascript
使用vue-router为每个路由配置各自的title
2018/07/30 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
nodejs实现获取本地文件夹下图片信息功能示例
2019/06/22 NodeJs
微信小程序实现下拉框功能
2019/07/16 Javascript
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
Python 加密的实例详解
2017/10/09 Python
python pandas读取csv后,获取列标签的方法
2018/11/12 Python
Python批量修改图片分辨率的实例代码
2019/07/04 Python
Python numpy.zero() 初始化矩阵实例
2019/11/27 Python
解决pycharm下pyuic工具使用的问题
2020/04/08 Python
Python unittest基本使用方法代码实例
2020/06/29 Python
如何使用pycharm连接Databricks的步骤详解
2020/09/23 Python
python eventlet绿化和patch原理
2020/11/21 Python
PPP协议组成及简述协议协商的基本过程
2015/05/28 面试题
承诺书怎么写
2014/03/26 职场文书
小学生感恩父母演讲稿
2014/08/28 职场文书
2014党员民主评议个人总结
2014/09/10 职场文书
沙滩主题婚礼活动策划方案
2014/09/15 职场文书
个园导游词
2015/02/04 职场文书
win11系统中dhcp服务异常什么意思? Win11 DHCP服务异常修复方法
2022/04/08 数码科技