心跳检测步骤:
TCP 是面向连接的,UDP 是面向无连接的;故 TCP 需要建立连接和断开连接,UDP 不需要。
TCP 是流协议,UDP 是数据包协议;故 TCP 数据没有大小限制,UDP 数据报有大小限制(UDP 协议本身限制、数据链路层的 MTU、缓存区大小)。
TCP 是可靠协议,UDP 是不可靠协议;故 TCP 会处理数据丢包重发以及乱序等情况,UDP 则不会处理。
这篇文章将包含以下几个主题:
1BLE的实际吞吐量是多少?
2蓝牙5的新2M PHY用于数据传输
3影响/确定数据吞吐量的因素有哪些?
4如何计算应用程序中的数据吞吐量?
5如何最大化数据吞吐量?
蓝牙5定义的 LE 2M PHY以及蓝牙4x协议 LE 1M PHY都称为未编码PHY,因为它们每位数据使用1个符号表示(与使用S=2或S=8的新LE编码PHY相比)。
我们需要明白各大芯片厂商数据手册宣传的速度(1 Mbps和新的2 Mbps)仅仅只是理论值(空中速率),并且在应用程序中吞吐量会被削减。原因有多种,我们将在下面一一介绍。
蓝牙5“2x速度”需要硬件支持,因此老的设备/芯片/模块将不支持蓝牙5 2M PHY(市面已经有手机支持蓝牙5 2M PHY)。要注意,为了实现更高吞吐量,需要两个BLE设备相互都支持LE 2M PHY。
另一个需要明确的是,当使用更高速度的PHY时,实际上功耗可以做的更低(传输相同数量的数据,时间短功耗低)。这是因为减少了芯片工作时间而又没有增加发射功率。反过来这样做改善了与24 GHz频谱内的其他无线技术的共存(也是由于减少了无线电工作时间,减少2,4G带宽的占用)。
为什么不可能达到BLE的理论速度?
1 Mbps(LE 1M PHY),2 Mbps(LE 2M PHY),125 kbps和500 kbps(均使用LE编码PHY,S = 8和S = 2)的数据速率是无线电在空中的速率传输数据,但由于以下原因,应用程序吞吐量是达不到该理论值:
1蓝牙规范限制每个连接间隔的数据包数量
2数据包之间的帧间间隔(IFS)延迟(150 us)
3即使没有可用于传输的数据,也需要从设备发送空数据包
4数据包开销 - 并非数据包中的所有字节都用于有效负载
为了更好地理解这些因素并了解影响应用程序吞吐量的因素,我们必须深入了解数据包格式。 下图显示了LE 1M PHY和2M PHY数据包的外观:
我们感兴趣的部分(真正定义应用程序数据的部分)是ATT Payload。 从图中可以看出,蓝牙低功耗中的每一层都使用了许多额外开销字节。
在40和41中,最大ATT有效载荷为20个字节。
在42和50中,称为数据长度扩展(DLE)的新功能允许ATT有效载荷最多可容纳244个字节的数据。
蓝牙5速:使用新的2M PHY实现2倍速
首先了解下蓝牙5中使用新LE 2M PHY的局限性:
1不能用于主要广播信道(37,38,39)。
2可用于与数据包在同一通道上发送的辅助“辅助数据包”(37个通道:0-36)。
要了解有关主要和次要广告的更多信息,请参阅我之前的文章细说BLUETOOTH 5 2X 数据吞吐量
蓝牙5规格书有说明,LE 1M PHY是强制性的,而LE 2M PHY是可选的,因此,并非所有声称支持蓝牙5的芯片都必须能够处理更高的吞吐量。
LE 2M PHY上可以发生从端广播模式和主端扫描模式,然后使用LE 2M PHY在第二广告信道上进行连接。
用户交互数据从一个设备传输到另一个设备是发生在两个设备的连接阶段。连接的设备可以通过更新PHY来协商使用不同PHY。它可以在建立连接后由从设备或主设备发起,但主设备最终将决定哪个PHY(基于从设备的请求和主设备支持的PHY)。
下面一些因素会影响BLE应用程序的数据吞吐量:
1使用的PHY(LE 1M vs LE 2M与LE编码(S = 2或S = 8))
2连接间隔
3每个连接间隔的最大数据包数
4ATT最大传输单元(ATT MTU)
5数据长度扩展(DLE)
6 *** 作类型:写入响应与写入无响应,指示与通知
7帧间间隔(IFS):后续数据包之间的时间间隔(150 us)
8传输空包
9数据包开销 - 并非数据包中的所有字节都用于应用程序有效负载
根据这9点,我们一点一点详细地讨论。
PHY
蓝牙5中基本上有三种PHY:原始的1 Mbps PHY,新的2 Mbps和编码的PHY(S = 2或S = 8)。所使用的PHY将直接影响您可以实现的最大数据吞吐量,因为它确定了通过无线方式发送数据包的实际原始数据速率。
每个连接事件的连接间隔和最大数据包
连接间隔有效地确定在一个连接事件期间可以发送多少数据包。值越高,在一个连接事件中可以发送的数据包越多(某些设备达到某个限制)。
BLE连接间隔和事件
每个连接事件的数据包数量取决于设备和BLE堆栈,因此它受到限制,并且在特定设备上的设备和堆栈版本之间有所不同。此值还取决于设备的 *** 作,因此无线电可能必须处理其他事件,并且每个连接事件发送的数据包数量可能达不到堆栈允许的最大值。例如,iOS和Android之间的数量不同,也会根据设备上运行的 *** 作系统版本而有所不同。
数据长度扩展(DLE)
此功能允许数据包大小保持更大的有效负载(最多251个字节,而禁用时为27个字节)。此功能是在蓝牙规范42版中引入的。
ATT最大传输单元(ATT MTU)
ATT MTU确定发送器和接收器可以处理的最大数据量以及它们可以保存在缓冲器中的数据量。
MTU值影响开销数据量(特别是3个字节的ATT头)。允许的最小ATT MTU是27个字节。这允许最多20个字节的ATT有效载荷(3个字节用于ATT报头,4个字节用于L2CAP报头)。
对于MTU值有多高,每个规范没有限制,但使用中的特定堆栈可能有其自身的局限性。例如,如果启用DLE,则最多可以传输251 - 4 = 247个字节(扣除L2CAP标头大小后)。在考虑ATT报头(3个字节)之后,我们留下了244个字节用于实际的ATT有效载荷数据。如果MTU至少为247字节,则MTU将适合一个单独的数据包。如果MTU大于247字节,则MTU将跨越多个分组,导致吞吐量下降(由于分组开销和分组之间的定时)。
有效MTU由客户端和服务器支持的ATT MTU的最小值确定。例如,如果客户端支持100字节的ATT MTU并且服务器响应它支持150字节的ATT MTU,则客户端将决定用于从其上进行连接的ATT MTU是100字节。
*** 作类型:写入响应与写入无响应,指示与通知
如果需要高吞吐量,那么我们可以使用Write without response或Notifications将数据从客户端传输到服务器以及从服务器传输到客户端。这些 *** 作不需要其他设备确认收到数据并在下一个数据块发送之前做出响应。
帧间间隔(IFS):连续数据包之间的时间延迟(150 us)
从蓝牙规范:
传输空包
如果接收数据的设备没有要发回的数据,则仍需要按照蓝牙规范发送空数据包。
数据包开销
正如我们在数据包格式图中看到的那样,数据包包含一些不计入应用程序数据(ATT数据)的开销数据。基本上,这些字节将消耗部分传输数据速率,而不考虑作为应用程序数据的一部分发送的任何字节。
计算应用程序数据吞吐量
敲黑板,画重点,正如我们之前提到的,有如下些因数会影响数据吞吐量:
1使用蓝牙版本和PHY
2DLE:数据长度扩展 - 启用与否
3ATT MTU值
4连接间隔
5每个连接事件的最大数据包数
6 *** 作(写入响应与写入没有响应,以及通知与指示)
7帧间间隔(IFS):150微秒
蓝牙版本和PHY确定原始数据传输速率。例如,如果我们使用蓝牙版本42和LE 1M PHY,则传输速率为1 Mbps。另一方面,如果我们使用蓝牙5 S = 8的 LE编码PHY,则数据速率降至125 kbps。
DLE,ATT MTU,连接间隔,每个连接间隔的最大数据包数, *** 作和IFS都是用于实际数据传输时间。
数据包格式在传输的数据量是实际应用程序数据方面起着重要作用。 LE 1M PHY和LE 2M PHY都具有类似的数据包格式。 LE编码PHY具有明显不同的数据包格式,因此我们将分别查看这两种情况。
LE 1M PHY和LE 2M PHY计算
返回参考LE未编码PHY的数据包格式:
针对不同PHY,数据开销略有不同。 对于1M PHY,前导码是1字节,而对于2M PHY,前导码是2字节。 MIC字段是可选字段,仅用于加密连接。 为简单起见,我们只考虑未加密的连接 - 对于加密的情况,它只是增加了4个字节的开销。
对于LE编码PHY,数据包格式如下所示(来自蓝牙50规范第6卷,第B部分,第22节):
计算吞吐量的步骤(以Mbps为单位):
为简单起见,我们做假设如下:
1未启用加密(数据包中不包含MIC字段)。
2我们感兴趣的是单方向的吞吐量(例如Master to Slave),所以我们假设另一个方向只传输空数据包。
3写入时,对方无需响应(No Ack)。
步骤:
确定正在使用的PHY并记下原始数据传输速率
例如。 对于1M PHY - > 1 Mbps,对于编码PHY和S = 8 - > 125 kbps
确定从接收器发送一个数据包和空包的时间。
可以发送一个数据包的时间包括以下内容:
Data_Packet_Time =发送空包的时间+ IFS +发送实际数据包+ IFS的时间。
空包传输时间可以如下计算:传输空包的时间=空包大小/原始数据速率
空包将包含以下字段:前导 + 访问地址(access address)+ LL头+ CRC。
对于1M PHY,前导将为1字节,因此空包的总大小= 1 + 4 + 2 + 3字节= 10字节=80位。
(对于2M PHY,空数据包的大小将为88位,因为Premable是2个字节而不是1个字节)。基于此,传输空1M PHY数据包的时间将是:
传输空数据包的时间=空数据包大小/原始数据速率= 80位/ 1兆位/秒= 80微秒数据包将包含数据包格式图中列出的所有字段,但MIC字段除外(加密禁用)。传输数据包的时间=数据包size / raw data rate如果我们启用了DLE并且ATT MTU等于一个数据包中允许的最大字节数:247个字节,那么我们可以将数据包大小计算为:
数据包大小= 1 + 4 + 2 + 4 + 247 + 3字节= 265字节= 265 8位= 2088 bit
发送数据包的时间= 2088位/ 1 Mbps = 2,088us
Data_Packet_Time =发送空包的时间+ IFS +发送实际数据包的时间+ IFS = 80 + 2 150 + 2088 = 2,468us
为了比较,在2M PHY的情况下,它将是:
Data_Packet_Time =发送空包的时间+ IFS +发送实际数据包的时间+ IFS = 88/2 + 2 150 +(2 + 4 + 2 + 4 + 247 + 3) 8/2 = 1,392us
当启用DLE并且ATT MTU设置为小于247时,会产生更多开销(因为现在大于ATT MTU的数据被分成更多数据包)。例如,假设我们将ATT MTU设置为158,那么为了传输244个字节的应用程序数据,我们需要两个数据包而不是一个,导致吞吐量因字节开销增加而增加而增加数据包之间的IFS。
在另一种情况下,我们可以禁用DLE(有效负载大小最多27个字节)和ATT MTU大于27个字节。在这里,这也将导致需要为相同数量的数据发送更多数据包,从而导致吞吐量下降。
注意:用于计算上面使用的数据和空数据包大小的方法可以用于计算LE编码PHY。
确定在一个连接间隔期间可以传输多少数据包
前一篇文章讲过,这种计算并不总是纯粹的数学计算 - 需要考虑使用的堆栈和设备的限制。在蓝牙芯片供应商的SDK中,通常在其文档中会列出最大值。iOS和Android的最大值随 *** 作系统版本而变化,所以要弄清楚并不容易。
一旦计算出最大值,就可以计算出适合所选连接间隔的最大理论数据包数。例如,如果我们的连接间隔为75毫秒(规范允许的最低值),则对于上面的示例(使用1M PHY,启用DLE):
每个连接间隔的最大数据包数= [连接间隔/ Data_Packet_Time],其中[]舍入到最大整数(整数)。
每个连接间隔的最大数据包数= [75 1,000微秒/ 2,468微秒] = 3个数据包
通常,这个数字是不现实的,因为在连续的连接事件上发送的数据包之间存在时间延迟。因此,对于我们的示例,我们将使用2个数据包而不是3个数据包。
一旦我们计算出每个连接间隔可以传输的最大数据包数,我们就可以计算出数据吞吐量:
数据吞吐量 = 每个连接间隔的数据/连接间隔 = 每个连接间隔的数据包数量每个数据包/连接间隔的数据大小
= 2 244 8位/75毫秒= 520,533位/秒〜= 508kbps
大家会认为,连接间隔越小,速率肯定更高,然,并不是。
下面就根据真实测试数据和计算理论值一一对比。
如有需要理论测试值计算推导的朋友,可以后台跟我联系。
总结:
路由器,蓝牙,手机wifi等24G的设备干扰,测试设备主从之间的距离,设备之间存在障碍等因数都会影响测试结果。上面列出的测试值和理论值,可能实际环境中的测量数据吞吐量不一致。干扰和传输/接收错误会影响数据吞吐量(重试,数据丢失和连接事件关闭会导致吞吐量降低)。 但本文详细分析了所有和速率相关的因素,在实际使用中,大家可以自由DIY
应用场景 :在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。
更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活
什么是心跳机制?
就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。
发包方:可以是客户也可以是服务端,看哪边实现方便合理。
心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没
有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40
秒比较不错。如果实在要求高,那就在6-9秒。
socket的send和recv是同时支持TCP和UDP的。从这两个函数的设计可以看出,协议简单来说就是读写数据。
socket的选项是 SOCK_STREAM 。
send的返回值>0时,表示实际发送了多少字节。 注意: 只是copy到系统缓存里,系统决定什么时候会发送这些数据。
send的返回值==0时,这个在send空串时会发生,是正常的。
send的返回值<0时(只会等于-1吧),需要检查errno,当 errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN 时,连接正常,可以稍后再试。其他的就是连接异常了。
recv的返回值>0时,表示实际接受到多少字节。
recv的返回值==0时, 表示连接断开 ,也就是收到了FIN或者RST。
recv的返回值<0时,检查errno,和send类似。
socket的选项是 SOCK_DGRAM 。
send的返回值>0时, 返回值应该等于发送的数据长度 。如果send的数据大于MTU,会在IP层分片,到达目标机器后IP层重组。
send的返回值==0时,这个只在发送空串时出现。 注意: 真的会发送空数据的。
send的返回值<0时,检查errno,确定连接是否还正常。一般不会发生吧,UDP的send是直接发送出去的。
recv的返回值>0时, 收到一个完整的数据包 。这个完整性是有IP层保证的。
recv的返回值==0时, 收到空包,这和TCP有很大不同 。
recv的返回值<0时,检查errno,确定socket是否正常。
PS: UDP还有两个函数 sendto 和 recvfrom 。客户端在调用connect后,才能用 send 和 recv , 服务器端只能用 sendto 和 recvfrom 。
UDP无连接,无顺序,自然不能代替TCP。
TCP是流式协议,需要应用层确认数据是否接受完整,也不能代替UDP。
应用要同时支持两种协议,得在上层做包装。有个KCP,使用UDP模拟TCP。
前几天景安的客服给我说景安的VPS也用这种模式,昨天试用了下,效果不错,打算把我的云VPS升级到快云,哈哈本篇教程的主要内容:
准备的工具:
putty
如果你一开始没有设置ECS的密码,或者想修改ECS的密码,可点击屏幕的右下方的“忘记云服务器登陆密码”的“重置密码”。
在重置密码窗口中,输入新的密码。注意新密码的字符要求。
安装并打开PuTTY
在Session配置中,输入HostName(或者IP地址),端口号22,连接类型选择SSH,配置完成后,点击下方的“Open”。
如果需要将该连接会话保存,则可以在下方Saved Sessions输入框中输入该连接会话的名称,点右侧的“Save”。
小技巧:
PuTTY其默认的配置是当用户一段时间内没有进行输入 *** 作时,便会自动断开连接。此时用户在PuTTY界面上进行键盘输入或者鼠标 *** 作,都是没有任何反应的,就好像死机一般。过一会儿PuTTY会提示说“连接已断开”。为解决该问题,需要在PuTTY的连接属性处修改一处配置。
此处将默认的0(0为关闭),改为10或其他数字(此处参数的意思为,PuTTY软件过几秒钟发一个空包给服务器,用以保持与服务器会话的连接,默认设置为0是关闭,不发空包)。
输入用户名:root,回车。
继续输入密码。(Linux命令行输入密码是没有任何提示和显示的,尽管按顺序输完,回车即可)
成功登录云服务器,最下方会出现欢迎信息。
此时第一件事是创建一个用户账号。
在上面的命令中
pwd是查看当前路径
useradd 是增加用户,同时给用户设置了一个根目录,/home/funeng,后面是用户名 funeng
passwd 是给用户设置密码,后面跟的是用户名funeng
在下面的提示框里输入新的密码,回车之后再次输入一次。依然是不显示任何符号。
新用户创建完成之后,便可以使用新用户登录了。
loginas:输入新用户名funeng
password:输入密码,回车,便以此新用户登录了系统。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)