python 心电处理包_python 黏包现象及其解决方案
一、数据缓冲区
缓冲区(buffer),它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,显然缓冲区是具有一定大小的。
二、为什么要缓冲区 (详情参考:https://www.cnblogs.com/mlgjb/p/7991903.html)
1.可以解除高速设备与低速设备的不匹配,高速设备需要等待低速设备的制约关系,数据可以直接送往缓冲区,高速设备不用再等待低速设备,提高了计算机的效率。
2.可以减少数据的读写次数,如果每次数据只传输一点数据,就需要传送很多次,这样会浪费很多时间,因为开始读写与终止读写所需要的时间很长,如果将数据送往缓冲区,待缓冲区满后再进行传送会大大减少读写次数,这样就可以节省很多时间。
三、粘包现象
1、小数据传输粘包
源代码:
importsocket
server=socket.socket()
server.bind(('127.0.0.1',8001))
server.listen()
conn,addr=server.accept()
msg_1=conn.recv(1024).decode("utf-8")
msg_2=conn.recv(1024).decode("utf-8")print("客户端>>>",msg_1)print("客户端>>>",msg_2)
conn.close()
server.close()
黏包现象服务端
importsocketimporttime
client=socket.socket()
client.connect(('127.0.0.1', 8001))
client.send(b'123')#time.sleep(0.1) 加入时间缓冲,让每次传入和接受的数据有序
client.send(b'456')
client.close()
黏包现象客户端
黏包现象粗略的解释:数据在传输过程中,未来得及按照先后次序传输和接受,数据都进入了数据缓冲区中,再接受的数据时候,不知道按照怎么的数据长度接受,就按照给定的1024的长度接收,因此出现了黏包.
解决方案:
方案一、传输过程中每次都告诉对方应该如何接收数据。
方案二、把传输和接受的间隔加大,保证每次都能顺利的满足一个接着一个传输。(time.sleep(0.1))
2、大数据传输粘包(模拟cmd指令)
源代码:
importsubprocessimportsocketimporttime
server=socket.socket()#创建socket对象
server.bind(('127.0.0.1',8001))#绑定ip_port
server.listen()#监听
conn,addr=server.accept()#等待连接,获取连接通道和地址
while 1:
time.sleep(0.1)#减少内存占用
cmd_msg=conn.recv(1024).decode("utf-8")#判断是否结束doc指令读取
if cmd_msg=="exit" or cmd_msg=="exit()":break
else:#创建读取cmd指令对象
obj_sub=subprocess.Popen(
cmd_msg,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
out_info=obj_sub.stdout.read()
err_info=obj_sub.stderr.read()iferr_info:#不存在该命令则输出错误信息,并打印字节数
conn.send(err_info)print(len(err_info))else:#存在输入的命令则发送指令执行的结果,并打印字节数
conn.send(out_info)print(len(out_info))
conn.close()
server.close()
大数据黏包现象服务器
importsocket
client=socket.socket()#创建客户端对象
client.connect(('127.0.0.1', 8001))#连接服务器的ip_port
while 1:
cmd=input("cmd>>>")
client.send(cmd.encode("utf-8"))#判断是否为退出指令
if cmd=="exit" or cmd=="exit()":break
else:#接受客服端返回信息
out=client.recv(1024).decode("gbk")print(out)
client.close()
大数据黏包现象客户端
结果显示:
1 C:\Python36\python.exe "F:/qishi/day 28 黏包 合法性链接/黏包现象/黏包现象2客户端.py"
2 cmd>>>ipconfig -all3
4 Windows IP 配置5
6 主机名 . . . . . . . . . . . . . : DESKTOP-MT7JLPA7 主 DNS 后缀 . . . . . . . . . . . :8 节点类型 . . . . . . . . . . . . : 混合9 IP 路由已启用 . . . . . . . . . . : 否10 WINS 代理已启用 . . . . . . . . . : 否11
12 无线局域网适配器 WLAN:13
14 媒体状态 . . . . . . . . . . . . : 媒体已断开连接15 连接特定的 DNS 后缀 . . . . . . . :16 描述. . . . . . . . . . . . . . . : Qualcomm Atheros AR9485WB-EG Wireless Network Adapter17 物理地址. . . . . . . . . . . . . : BC-30-7D-96-2D-2B18 DHCP 已启用 . . . . . . . . . . . : 是19 自动配置已启用. . . . . . . . . . : 是20
21 无线局域网适配器 本地连接* 1:22
23 媒体状态 . . . . . . . . . . . . : 媒体已断开连接24 连接特定的 DNS 后缀 . . . . . . . :25 描述. . . . . . . . . . . . . . . : Microsoft Wi-Fi Direct Virtual Adapter26 物理地址. . . . . . . . . . . . . : 1E-30-7D-96-2D-2B27 DHCP 已启用 . . . . . . . . . . . : 是28 自动配置已启用. . . . . . . . . . : 是29
30 以太网适配器 以太网:31
32 连接特定的 DNS 后缀 . . . . .33 cmd>>>dir34 . . :35 描述. . . . . . . . . . . . . . . : Realtek PCIe GBE Family Controller36 物理地址. . . . . . . . . . . . . : C4-54-44-F5-84-6A37 DHCP 已启用 . . . . . . . . . . . : 是38 自动配置已启用. . . . . . . . . . : 是39 本地链接 IPv6 地址. . . . . . . . : fe80::64a8:6af:a71b:edad%5(首选)40 IPv4 地址 . . . . . . . . . . . . : 192.168.12.51(首选)41 子网掩码 . . . . . . . . . . . . : 255.255.255.0
42 获得租约的时间 . . . . . . . . . : 2018年11月26日 15:01:29
43 租约过期的时间 . . . . . . . . . : 2018年11月27日 15:01:28
44 默认网关. . . . . . . . . . . . . : 192.168.12.254
45 DHCP 服务器 . . . . . . . . . . . : 192.168.12.254
46 DHCPv6 IAID . . . . . . . . . . . : 63198276
47 DHCPv6 客户端 DUID . . . . . . . : 00-01-00-01-23-7C-84-72-C4-54-44-F5-84-6A48 DNS 服务器 . . . . . . . . . . . : 114.114.114.114
49 TCPIP 上的 NetBIOS . . . . . . . : 已启用50
51 cmd>>>
客户端显示结果
C:\Python36\python.exe "F:/qishi/day 28 黏包 合法性链接/黏包现象/黏包现象2服务器.py"ipconfig-all 命令执行结果长度 1912dir 命令执行结果长度505
服务端显示结果
现象简述:首先执行了一次ipconfig -all,他的结果数据长度是1912,而我们接受的数据长度是1024,之后又执行了一次dir,dir结果长度是505,我们再一次接受的数据,依旧是ipconfig -all 结果数据.出现了黏包现象.
黏包现象成因:执行的数据进入缓冲区,并且数据的大小大于接受数据的大小,因此我们一次接受只能接受1024个字节,之后又执行一个命令后,命令的结果又会进入数据缓冲区,所有我们接受的数据显示的是上一个命令残余的数据.我们每次接受的数据都是1024,还有可能出现多命令的数据同时出现的风险.
解决方案:
方案一、按照发送数据的长度接受数据,由于缓冲区数据容量有限,我们采用循环接受数据的方法接受大数据。
方案二、把数据的长度信息与数据信息合并一次性发给接受端,接收端先提出数据长度,再按照数据长度接受数据。
方案一源代码:
1 importsubprocess2 importsocket3 importtime4 server=socket.socket()#创建socket对象
5
6 server.bind(('127.0.0.1',8001))#绑定ip_port
7 server.listen()#监听
8 conn,addr=server.accept()#等待连接,获取连接通道和地址
9
10 while 1:11 time.sleep(0.1)#减少内存占用
12 cmd_msg=conn.recv(1024).decode("utf-8")13 #判断是否结束doc指令读取
14 if cmd_msg=="exit" or cmd_msg=="exit()":15 break
16 else:17 #创建读取cmd指令对象
18 obj_sub=subprocess.Popen(19 cmd_msg,20 shell=True,21 stdout=subprocess.PIPE,#标准化输出
22 stderr=subprocess.PIPE #标准化错误输出
23 )24 out_info=obj_sub.stdout.read()25
26 err_info=obj_sub.stderr.read()27
28
29 iferr_info:30 #不存在该命令则输出错误信息,并打印字节数
31 data_len =len(err_info)32 all_send_datalen=033 print(f"{cmd_msg} 命令执行结果长度", data_len)34 #把数据长度发送给接收端
35 conn.send(str(data_len).encode("utf-8"))36 while all_send_datalen
37 #递增式改变截取位置
38 every_send_data=err_info[all_send_datalen:all_send_datalen+1024]39 conn.send(err_info)40 all_send_datalen+=len(every_send_data)41
42 else:43 #存在输入的命令则发送指令执行的结果,并打印字节数
44 data_len =len(out_info)45
46 all_send_datalen =047 print(f"{cmd_msg} 命令执行结果长度:", data_len)48
49 #把数据长度发送给接收端
50 conn.send(str(data_len).encode("utf-8"))51 while all_send_datalen < data_len: #当发送的数据小于数据总长就不断的放送
52 #递增式改变截取位置
53 #每1024个字节发一次
54 every_send_data = out_info[all_send_datalen:all_send_datalen + 1024]55 conn.send(every_send_data)56
57 all_send_datalen +=len(every_send_data)58
59 conn.close()60 server.close()
大数据黏包服务器
1 importsocket2 client=socket.socket()#创建客户端对象
3 client.connect(('127.0.0.1', 8001))#连接服务器的ip_port
4
5 while 1:6
7 cmd=input("cmd>>>")8 client.send(cmd.encode("utf-8"))9 #判断是否为退出指令
10 if cmd=="exit" or cmd=="exit()":11 break
12 else:13 #客客户端接受返回信息
14 data_len=client.recv(1024).decode("utf-8")15 int_data_len=int(data_len)16 print(int_data_len)17 #接受的字节个数,计数比较
18 all_recv_datalen=019 #用于接收到的字节拼接
20 all_data=b''
21 #循环接受数据
22 while all_recv_datalen<23>
24 every_recv_data=client.recv(1024)25 all_recv_datalen+=len(every_recv_data)26 all_data +=every_recv_data27 #输出打印
28 print(all_data.decode("gbk"))29
30 client.close()
大数据黏包客户端
方案二struct打包:
struct操作简介
importstruct#打包pack#struct.pack(格式,数据)#a=231546789#b=struct.pack("i",a)#print(b)#b'\xa5\x1f\xcd\r'
#解包unpack,结果是元祖#struct.unpack(格式,数据)
c=struct.unpack("i",b'\xa5\x1f\xcd\r')print(c) #(231546789,)
a=c[0]print(a)#231546789
源码:
importsocketimportsubprocessimportstruct
server=socket.socket()
ip_port= ('127.0.0.1',8001)
data_full_len= 0 #统计发送数据的长度
server.bind(ip_port)
server.listen()
conn,addr=server.accept()while 1:
from_client_cmd= conn.recv(1024).decode('utf-8')
sub_obj=subprocess.Popen(
from_client_cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)#subprocess对象.read 得到的结果是bytes类型的
cmd_res =sub_obj.stdout.read()
data_len= len(cmd_res) #总数据长度
data_len_str =str(data_len)print('结果长度>>>',data_len)#将真实数据长度打包成4个字节的数据
struct_data_len = struct.pack('i',data_len)
conn.send(struct_data_len+ cmd_res)
大数据黏包struct服务器
importjsonimportsocketimportstruct
client=socket.socket()
ip_port= ('127.0.0.1',8001)
client.connect(ip_port)
all_recv_len=0
all_data_byte= b''
while 1:
client_cmd= input('请输入系统指令>>>')
client.send(client_cmd.encode('utf-8'))#先接收4个字节,这4个字节是真实数据长度加工成的
recv_data_len = client.recv(4)#将4个字节长度的数据,解包成后面真实数据的长度
real_data_len = struct.unpack('i',recv_data_len)[0]print(real_data_len)
server_result=client.recv(real_data_len)print(server_result.decode('gbk'))
大数据黏包struct客户端
加强版:
1 importstruct2 importsocket3 importsubprocess4 importtime5
6 server=socket.socket()7 server.bind(("127.0.0.1",8001))8 server.listen()9 conn,addr=server.accept()10 while 1:11 time.sleep(0.1)12 cmd_msg=conn.recv(1024).decode("utf-8")13 obj_sub=subprocess.Popen(14 cmd_msg,15 shell=True,16 stdout=subprocess.PIPE,17 stderr=subprocess.PIPE18 )19 cmd_out=obj_sub.stdout.read()20 cmd_erro=obj_sub.stderr.read()21 ifobj_sub.stdout:22 out_len=len(cmd_out)23 print(cmd_msg+"\t"+str(out_len))24 b_out_len=struct.pack("i",out_len)25 conn.send(b_out_len+cmd_out)26
27 else:28 err_len =len(cmd_erro)29 int(cmd_msg + "\t" +str(err_len))30 b_err_len = struct.pack("i", err_len)31 conn.send(b_err_len+cmd_erro)32 conn.close()33 server.close()
完整版服务器
1 importstruct2 importsocket3 importsubprocess4 importtime5
6 client=socket.socket()7 client.connect(("127.0.0.1", 8001))8 while 1:9 time.sleep(0.1)10 cmd=input("cmd>>>").encode("utf-8")11 client.send(cmd)12 #接受数据
13 data_len_pack=client.recv(4)14 data_len=struct.unpack("i",data_len_pack)[0]15 print(data_len)16 data=client.recv(data_len).decode("gbk")17 print(data)18 client.close()
完整版客服端
23>
python 心电处理包_python 黏包现象及其解决方案相关推荐
- Python学习日记(三十一) 黏包问题
import subprocessres = subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PI ...
- python自带哪些包_python各个包的用途
python中的多个包的用途 1.Numpy Numpy提供了两种基本的对象:ndarray和ufunc.ndarray是存储单一数据类型的多维数组,而ufunc是能够对数组进行处理的函数. N维数组 ...
- 【Python基础篇021】黏包现象丨udp的socket服务
- python queue模块安装_Python queue包_程序模块 - PyPI - Python中文网
沃特?另一个消息队列? 考虑到消息队列的激增,人们可能倾向于相信 发明更多不是答案.使用现有的解决方案是 多次尝试与大多数现有的消息队列产品. 其他的失败(对于我们的用例). queuey是用来处理大 ...
- python ssh登陆模块_Python sshh包_程序模块 - PyPI - Python中文网
sshh是一个ssh帮助工具,用于在ssh代理中批量注册ssh私钥. sshh的主要目的是避免在 在ssh代理中注册的密钥数超过一定数量.当 当服务器设置私钥上限时,超过了密钥尝试的上限 严格的尝试. ...
- python app开发模块_Python pytkapp包_程序模块 - PyPI - Python中文网
用于开发应用程序的python包 多文档/单文档界面 利用tkinter库和附加tkinter集 小部件. 查看可用演示: pytkapp/demo/run_ptapoptionsdemo.py-为选 ...
- python使用pkg包_Python deb-pkg-tools包_程序模块 - PyPI - Python中文网
python包deb-pkg-tools是要构建和 检查Debian binary packages和二进制包的存储库.它的 主要用例是自动化构建. 一些功能在命令行界面中公开(如下所述) 因为在sh ...
- python 统计分析 包_Python 数据分析包:pandas 基础
pandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 类似于 Numpy 的核心是 ndarray,pandas 也是围绕着 Series 和 DataFrame 两个核心数据 ...
- python什么是调用_Python中包(package)的调用方式
一.什么是Python Package 如何区分你看到的目录是一个Python Package包呢?其实很简单,你只要看这个名录下是否有"__init__.py"这个文件就好了,如 ...
最新文章
- Linux下批量杀掉筛选进程
- Android开发举步维艰,上弘法寺七七四十九天取得“真经”!
- Ubuntu 16.04 下 Vim安装
- Java——编译与反编译
- 远程服务器如何创建分支,git如何远程创建分支
- PopTheBubble —测量媒体偏差的产品创意
- 计算机安全概论论文,计算机安全探讨论文毕业论文(7篇).doc
- java 什么是迭代器
- php 调用图,php 缩略图类(附调用示例)
- 一个SQL SERVER功能模块表
- 多线程面试体系列(13):多线程同步内功心法——PV操作下
- 跟ArthurXF学从雅虎抓取股票数据的方法
- Linux连接mysql 出现Access denied for user ‘root‘@‘localhost‘(using password: YES)错误解决方案
- cass转换jpg_【转】南方CASS作原有地形图数字化--对扫描栅格图像进行校正及矢量化...
- VC写的手机qq聊天记录导出工具
- Unix传奇历史与回忆-读史使人明智,鉴以往而知未来
- 互联网晚报 | 9月1日 星期四 |​ 刘畊宏带货假燕窝公司已被吊销;比亚迪回应巴菲特减持;华为打车将全国扩张...
- Autonomous Driving in Adverse Weather Conditions: A Survey - 恶劣天气条件下的自动驾驶:一项调查 (arXiv 2021)
- 正太分布函数和反函数 标量值函数 (借鉴)
- 谷歌账号电子邮件怎么改_如何使用Google仅搜索您的电子邮件,事件和其他内容...
热门文章
- linux下php的安装,Linux下PHP安装
- macos安装vscode_如何使用VSCode进行PostgreSQL开发及调试
- 网易 html5,别再想不开做H5了
- 怎么用git将本地代码上传到远程服务器_git之如何把本地文件上传到远程仓库的指定位置...
- python多线程框架_基于python和bash的多线程任务框架 不要让cpu闲着了
- Java Currency getInstance()方法与示例
- c# contains_清单 .Contains()方法,以C#为例
- List 集合去重的 3 种方法
- 高质量SQL的30条建议!(后端必备)
- 面试官 | 什么是 Lambda?该如何使用?