当前位置: 首页 > news >正文

Android wifi常见问题及分析

参考 Android Network/WiFi 那些事儿

前言

本文将讨论几个有意思的网络问题,同时介绍 Android 上常见WiFi 问题的分析思路。

网络基础Q & A

一. 网络分层缘由

982ca07415304f4f98c784740e51cdc1.png

分层想必大家很熟悉,是否想过为何需要这样分层?

网上大多都是介绍每一层的职责,似乎对为何要分层很少提及。

从软件设计模式的角度来看,分层有点像MVC、MVP、MVVM 等Android 架构模式。

其本质是为了解耦,职责更加明确,修改的话只改一层即可,不至于牵一发而动全身。

通过分层,对外屏蔽其复杂性,这样出问题的话容易定位到问题。

每一层的职责又是什么呢?

传输层解决的是进程定位的问题、网络层解决数据包寻路的问题、数据链路层解决局域网传输的问题。

二. MAC 层扮演的角色

关于MAC 层扮演的角色,你可能会说因为ip 会变,mac 地址的话,不过这似乎并没有解释清楚。

首先,我们需要达成这样的一个共识:

网络包在到达最终目的地之前,是不知道目标mac 地址的,这期间会经历无数次mac 层封装ip 层的过程,比如某一次mac层包装ip层时,这时候的mac层地址并不一定是最终的目标mac地址。

有可能是相连的一台路由器的mac地址,解码之后看ip,发现ip 不在这个局域网内,然后再次包装一层mac 地址,发给相连(也有可能不是相连,反正就是根据某种规则规定的下一个路由器)路由器。

数据包上ip 地址的作用是在外网上投递用的,内网就不行了,必须要用mac,使用mac 其中一个原因是为了在局域网内确认到那台正确的计算机。

信息传递时候,需要知道的其实就是两个地址:

• 终点地址(Final destination address)

• 下一跳的地址(Next hop address)

IP地址本质上是终点地址,它在跳过路由器(hop)的时候不会改变,而MAC 地址则是下一跳的地址,每跳过一次路由器都会改变。

[引用1]

归纳下来一句话:

MAC 作用是局域网内寻址,IP 作用是网络寻址。

三. DHCP

0fb3f26bebee417e9dd014187994c7f6.png

从日志中看DHCP 的过程 (logcat & driver)

491add627ffe47eb8f28527fb74948fd.png

Q:DHCP Offer 和 DHCP ACK是广播包吗?

A:取决于client 端的ip 协议栈的能力,如果协议栈在初始化过程中,不接收单播IP报文,请在DHCP Discovery/ Request报文的Flags里明确告知服务器,设置BROADCAST flag = 1,服务器就用广播来和客户端通信。

Q:是否存在static ip 和DHCP Server 分配给Client 的ip 冲突的情况?

A:其实在最后的确认阶段,当Client收到DHCP Server发送的DHCP ACK 报文之后,并不会马上使用Server 分配的这个地址,而是会发送目的地址为Server 分配地址的ARP 请求报文作最后的确认(即免费ARP)。

如果没有检测到冲突,则将此地址与自己绑定。如果检测到冲突,就向DHCP Server发送DHCPDECLINE报文,在Request IP Address(option 50)字段填入Server提供的发生冲突的IP地址.发送完成后,等待一段时间再开始重新申请IP地址,直至申请到一个可用的IP地址。

四. TCP

我们接下来讨论TCP 的几个疑问

为何TCP 是三次握手,而挥手是四次

握手的作用是为了初始化双边的序列号,这个是众所周知的事情。

问题是:为何是三次握手?

其实TCP 的3次握手是优化的结果,它应该是4次握手,由于是从零开始的建立连接,因此将SYN的ACK及被动打开的SYN合并成一个SYN-ACK,仅此而已。

2e5820ba8fb240dc8c409799e82c2af6.png

为什么TCP的断链是4次挥手而不是3次?

其实这个问题可以换个问法:

为什么针对主动断开方的FIN的ACK以及本端的FIN不能合并?

因为TCP 连接是全双工的,握手阶段可以将ACK 和SYN 合并是因为此时没有数据上的连接,所以可以放心的合并。

然而,挥手阶段就不一样了,假设Client 端数据传输完了认为此时可以断开,而Server 端可能还有数据要传,为了避免数据丢失或者损坏,Server 端先发ACK,然后等数据传输完成后再发送FIN 和ACK。

1540806018eb49dd96406bae9a161ba3.png

上面提到的无论是三次握手还是四次挥手,其次数约定的核心是TCP 是全双工。

如果不理解这句话的话,不妨多看几遍上面的握手和挥手流程。

为何说TCP 是" 可靠 "协议

TCP 发送端和接收端并不存在真实的类似网络专线的东西,而是通过Client 和Server 各自维护一定数据结构(一种状态机),来记录和维护"连接"的状态。

TCP 作为这样一个抽象的协议,跑在不可靠的IP 协议之上,在一个不可靠的介质上传输,其本质不可能是可靠的。

既然下层链路不可靠,那么TCP 是如何实现所谓的可靠?

基于丢包检测以及超时重传

如何判断丢包和解决丢包的问题?

引入ACK 和 超时重传,事实上远没这么简单,复杂网络下,还会涉及到滑动窗口、拥塞控制等概念,受限篇幅,我们后续会另起一篇文章讨论拥塞控制。

超时时间内没收到Ack 则重发,可能是发的路上丢了也可能是Ack 丢了

e8ad01fa3a3f43a5acf142705b4043e3.png

图中绘制的是超时重传,还有一个经常被提及的快速重传,其本质也是超时重传,只是一个优化而已。

Q:快速重传时的优先级是怎样的?

A:

1. lost 数据段

IsLost (SeqNum):

This routine returns whether the given sequence number is

considered tobe lost. The routine returns truewheneither

DupThresh discontiguous SACKed sequences have arrived above

'SeqNum' or (DupThresh * SMSS) bytes with sequence numbers greater

than 'SeqNum' have been SACKed. Otherwise, the routine returns

false.

(摘自 RFC3517 A Conservative Selective Acknowledgment)

2. 新的尚未发送的数据段

3. 没有标记为LOST,没有标记为SACKed,没有重传过的数据段

Q:每个 seq 都需要一个 ack 吗?

A:这其实涉及一个概念:ACK 延迟确认

延迟确认可以让我们同时对多个接受的报文进行一次确认,又称之为累积确认

这样接收方就不必对每个报文都进行确认,接收到多个报文后如果延迟时间内没有报文到来,就发送下一个期望接收报文的 ack。

好处显而易见就是节省带宽,弊端也很明显那就是延迟带来的性能损失甚至会造成不必要的超时重传。

Q:RTO 依据RTT 计算出来准确吗?

A:某些场景下不准确会导致误判重传

“The Transmission Control Protocol (TCP) usesa retransmission timer to

ensure data delivery inthe absence ofany feedback from the remote data

receiver. The duration ofthis timer isreferred toasRTO (retransmission timeout).”

72d1b27ff3b349258614e9b2a0cc5744.png

根据RTT 计算出RTO 在内核中是一个比较复杂的过程,这里不展开讨论其细节,有兴趣的话可以看下 RFC 6298 的 The Basic Algorithm。

除了真实的网络丢包导致的RTO 之外,还有一种情况下的RTO 超时被称为虚假重传超时,比如突发拥塞导致的RTT 极速拉升、路由链路变更导致新RTT 较高、RTT 波动较大的受干扰无线环境下等都可能会出现这种情况。

WiFi 常见问题

我们平时在实际项目上,经常会遇到一些WiFi 相关的问题,比如连接不上、异常掉线等问题。我们打算例举出WiFi 常见问题,讨论其「一般分析思路」。

1. 连接问题

为何会出现连接失败?

比较常见的原因:

密码错误、Auth 失败、握手异常、DHCP 失败等。

一. 握手失败

1, 2 握手失败,通常是由于密码错误

17:29:23.276148 [ cds_ol][ 0x10cb45409a9][ 14:28:23.026125]wlan: [6161:D:QDF] DPT: 0379:255 EAPOL: [0] [M1] SA: ec:41:18:08:df:9d < --DA:bc:7f:a4:35:0a:95

17:29:23.276159[ soft_i][ 0x10cb454559e][ 14:28:23.027139] wlan:[ 0:D:QDF] DPT:0381:255EAPOL:[ 0] [ M2] SA:bc:7f:a4:35:0a:95--> DA: ec:41:18:08:df:9d

//重复进行1,2握手,间隔时间 1s

17:29:26.838232 [ cds_ol][ 0x10cb6a1b219][ 14:28:25.038825]wlan: [6161:D:QDF] DPT: 0384:255 EAPOL: [0] [M1] SA: ec:41:18:08:df:9d < --DA:bc:7f:a4:35:0a:95

17:29:26.838243[ soft_i][ 0x10cb6a1f966][ 14:28:25.039776] wlan:[ 0:D:QDF] DPT:0386:255EAPOL:[ 0] [ M2] SA:bc:7f:a4:35:0a:95--> DA: ec:41:18:08:df:9d

17:29:27.038660 [ cds_ol][ 0x10cb8eb8450][ 14:28:27.038427]wlan: [6161:D:QDF] DPT: 0389:255 EAPOL: [0] [M1] SA: ec:41:18:08:df:9d < --DA:bc:7f:a4:35:0a:95

17:29:29.043572[ soft_i][ 0x10cb8eba31f][ 14:28:27.038839] wlan:[ 0:D:QDF] DPT:0391:255EAPOL:[ 0] [ M2] SA:bc:7f:a4:35:0a:95--> DA: ec:41:18:08:df:9d

//重复两次后失败

17:29:29.043606 [ kworke][ 0x10cbb354e58][ 14:28:29.037922]wlan: [15785:D:MGMT _TXRX] tgt_mgmt _txrx_rx _frame_handler: 1043: Rcvd mgmt frame subtype c0 (frame type 10) from ec:41:18:08:df:9d, seq _num = 1049, rssi = -17 tsf_delta: 0

密码错误可以从driver 日志中进一步证实

03-0618: 23: 06.58565010241024D wpa_supplicant: wlan0: State:

4WAY_HANDSHAKE -> DISCONNECTED

03-0618: 23: 06.5861887491247D WifiHW : [ 1] getevent: IFNAME=wlan0 < 3>WPA:

4-Way Handshake failed - pre- sharedkeymay be incorrect

03-0618: 23: 06.5861987491247D WifiHW : [ 2] getevent:

IFNAME=wlan0 WPA:

4-Way Handshake failed - pre- sharedkeymay be incorrect

而3, 4 握手失败,通常是路由设置问题

10:31:35.954886 [ cds_ol][ 22131061630][ 18:33:35.944171]wlan: [12981:I:QDF] qdf _dp_display _proto_pkt_always: 2093: DPT: 1145:255 EAPOL: [0] [M1] SA: 30:0d:9e:5a:83:6f < --DA:64:a2:00:77:4a:94

10:31:35.954914[ soft_i][ 22131098001][ 18:33:35.946066] wlan:[ 0:I:QDF] qdf_dp_display_proto_pkt_always:2093:DPT:1147:255EAPOL:[ 0] [ M2] SA:64:a2:00:77:4a:94--> DA: 30:0d:9e:5a:83:6f

10:31:35.955028 [ cds_ol][ 22131150806][ 18:33:35.948815]wlan: [12981:I:QDF] qdf _dp_display _proto_pkt_always: 2093: DPT: 1150:255 EAPOL: [0] [M3] SA: 30:0d:9e:5a:83:6f < --DA:64:a2:00:77:4a:94

10:31:35.964895[ soft_i][ 22131186337][ 18:33:35.950667] wlan:[ 0:I:QDF] qdf_dp_display_proto_pkt_always:2093:DPT:1152:255EAPOL:[ 0] [ M4] SA:64:a2:00:77:4a:94--> DA: 30:0d:9e:5a:83:6f

//重复进行3,4握手,间隔时间1s

10:31:36.948740 [ cds_ol][ 22150330716][ 18:33:36.947769]wlan: [12981:I:QDF] qdf _dp_display _proto_pkt_always: 2093: DPT: 1173:255 EAPOL: [0] [M3] SA: 30:0d:9e:5a:83:6f < --DA:64:a2:00:77:4a:94

10:31:36.954601[ soft_i][ 22150370206][ 18:33:36.949827] wlan:[ 0:I:QDF] qdf_dp_display_proto_pkt_always:2093:DPT:1175:255EAPOL:[ 0] [ M4] SA:64:a2:00:77:4a:94--> DA: 30:0d:9e:5a:83:6f

10:31:37.964228 [ cds_ol][ 22169779798][ 18:33:37.960742]wlan: [12981:I:QDF] qdf _dp_display _proto_pkt_always: 2093: DPT: 1181:255 EAPOL: [0] [M3] SA: 30:0d:9e:5a:83:6f < --DA:64:a2:00:77:4a:94

10:31:37.964267[ soft_i][ 22169799422][ 18:33:37.961765] wlan:[ 0:I:QDF] qdf_dp_display_proto_pkt_always:2093:DPT:1183:255EAPOL:[ 0] [ M4] SA:64:a2:00:77:4a:94--> DA: 30:0d:9e:5a:83:6f

//重复两次后失败

10:31:38.948461 [ schedu][ 22188729766][ 18:33:38.947719]wlan: [12979:I:PE] Deauth RX: vdev 0 from 30:0d:9e:5a:83:6f for 64:a2:00:77:4a:94 RSSI = -48 reason 15 mlm state = 16, sme state = 11 systemrole = 3

二. DHCP 失败

//正常 IpClient.wlan0 StateMachine dump: 关键字"onProvisioningSuccess"

2021-02-07T09:29:31.941 - CMD_START wlan0/30 0 0 ProvisioningConfiguration{mEnableIPv4: true, mEnableIPv6: true, mEnablePreconnection: false

2021-02-07T09:29:32.033 - EVENT _PRE_DHCP _ACTION_COMPLETE wlan0/30 0 0 null [rcvd _in=RunningState, proc_in=RunningState]

2021-02-07T09:29:32.591 - INVOKE onProvisioningSuccess({{InterfaceName: wlan0 LinkAddresses: [ 192.168.31.45/24 ] DnsAddresses: [ /192.168.31.1 ]

//异常 IpClient.wlan0 StateMachine dump: 关键字"onProvisioningFailure"

2021-02-07T12:24:32.069 - CMD_START wlan0/20 0 0 ProvisioningConfiguration{mEnableIPv4: true, mEnableIPv6: true, mEnablePreconnection: false

2021-02-07T12:24:32.095 - EVENT_PRE_DHCP_ACTION_COMPLETE wlan0/20 0 0 null [rcvd_in=RunningState, proc_in=RunningState]

2021-02-07T12:25:08.071 - INVOKE onProvisioningFailure({{InterfaceName: wlan0 LinkAddresses: [ fe80::63aa:c19f:9cf:2868/64 ] DnsAddresses: [ ] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,8808040,262144,524288,6710886 Routes: [ fe80::/64 -> :: wlan0 ]}})

//正常 DHCP client:收到DHCP server分配的IP等信息

02-07 09:29:39.834 root 0 0 I [ soft_i][ 0x2d51ef84972][ 09:29:39.834889] wlan: [0:I:QDF] DHCP-D TX: SA:10:3f:44:af:8a:d4 DA:ff:ff:ff:ff:ff:ff msdu_id:861 status: succ

02-07 09:29:39.838 1073 2519 7028 D DhcpClient: Received packet: 10:3f:44:af:8a:d4 OFFER, ip /192.168.31.45, mask /255.255.255.0, DNS servers: /192.168.31.1 , gateways [/192.168.31.1] lease time 43200, domain null

//异常 DHCP client:没有收到DHCP server分配的IP等信息

[ 371.350648] [ soft_i][ 375560042590][ 12:24:32.098901] wlan: [0:I:QDF] DHCP-D TX: SA:e8:5a:8b:de:1f:43 DA:ff:ff:ff:ff:ff:ff msdu_id:1199 status: succ

分析:

通常是由于信号弱导致,因为DHCP 数据帧较大,在信号弱时会出现交互失败的情形,可以从日志中检查下rssi 值,并在信号佳的位置对比测试。

三. Auth 失败

2021-05-12 10:22:43.578458 [ schedu][ 589237120609][ 22:22:43.577742]wlan: [26358:I:PE] Auth TX: success

2021-05-12 10:22:43.578514 [ schedu][ 589237125306][ 22:22:43.577987]wlan: [26358:I:PE] Auth RX: vdev 1 sys role 3 lim _state 7 from 54:75:95:e7:6f:61 rssi -63 auth_alg 0 seq 3976

//正常情况下code 是0,这里的code 1表示路由拒绝认证,需要进一步看路由拒绝原因

2021-05-12 10:22:43.578519 [ schedu][ 589237125762][ 22:22:43.578011]wlan: [26358:E:PE] lim _process_auth _frame_type2: 740: rx Auth frame from peer with failure code 1 54:75:95:e7:6f:61

2021-05-12 10:22:43.578524 [ schedu][ 589237126959][ 22:22:43.578073]wlan: [26358:E:PE] lim _process_mlm _auth_cnf: 543: Auth Failure occurred

分析:

对应到driver 日志,通常会打印出Auth frame from peer with failure,其后跟的code 数值代表了本地失败的原因,正常情况下是0,这个值也可以通过sniffer 中auth帧的status值确定。

关于code 数值的含义可以查看 802.11 Association Status Codes

比如我们项目上之前还遇到过code 17这种情况

 

687db09453752352bea886c1a5f707a9.png

从表格中可以看出17表示被 AP 拒绝,说明连接AP 的STA 太多已超出了AP 负载能力。

2. 掉线问题

为何会出现异常掉线?

常见原因:

framework 断开、Beacon miss、Kickout、Nud failed、Rx disassoc or deauth等

在介绍常见的掉线问题之前,先回答这样一个问题:

如何判断是上层断线还是底层断线?

笔者经验而言:

1. 如果是底层断线,会先收到底层断线发上来的DISCONNECT Event,然后supplicant才把state 切到 DISCONENCTED。

2. 如果是上层断线,disconnection request会先到supplicant,supplicant state会先切到DISCONNECTED, 发送disconnect request 给driver 去真正断开wifi 连接。

从日志中判断的话,一个简单的方法是搜关键字:

wpa_supplicant: nl80211, wpa_supplicant: wlan0看打印关键日志的先后关系。

一. RSSI 信号差

搜索日志关键字 "processed=L2ConnectedState"

rec[ 902]: time= 03-0316: 01: 25.327processed=L2ConnectedState

org=ConnectedState dest=< null> what=CMD_RSSI_POLL screen= on560

//rssi 数值-52,说明此时信号较好

"stevenli_5G"88:c3: 97: 32:c6:cc rssi= -52f= 5805sc= 60link= 720tx= 0.1,

0.0, 0.0rx= 1.5bcn= 48014[ on: 2941tx: 831rx: 24period: 3009]

fromscreen [ on: 79247period: 154965] score= 60

分析:

判断当前信号强弱,我们通常是通过查看rssi 数值以及TX、RX数值来判断。

通常来讲,RSSI 数值较好是介于-40~-60 之间,<-65 则认为信号较差。

二. Beacon 超时

首先需要先明白一点:

Beacon 时间间隔是AP 设置的,一般是100ms一个, 和station 无关

原理机制(MTK平台):

首先Hw 会判断如果连续10个Beacon 没有收到,这时候会上报一个event 给 Fw,Fw收到这个Interrupt 之后,会重新设置 Linkdetect 的检查机制,拉大检查监听Beacon 的 interrupt 为96Ms ,如果接下来Hw 还是上报 Beacontimeout interrupt 。

这个时候Fw才真正上报 event 给 driver ,driver 收到这个Beacontimeout 之后,会延迟5S做一个重连,如果重连成功,此次Beacontimeout 不处理,认为是正常的。

如5S内还是重连不上,上报给Fwk 做断线处理。

< 6> [ 133.745238] (3)[ 827:main_thread][ wlan]

[827]aisIndicationOfMediaStateToHost:(AIS INFO) Postpone the indication of Disconnect for 5 seconds

分析:

通常是由于RSSI 信号差导致,不过如果当时的网络环境比较差,Noise 比较大,也会导致Beacon 无法收到,进而触发Beacontimeout。

三. ARP or DNS 异常

周期性检测DNS 状态过程中若发生fail,会触发断线

//关键字 "CMD_IP_REACHABILITY_LOST "或 "NUD_FAILED"

rec[135]: time=09-12 19:51:14.715 processed=L2ConnectedStateorg=ConnectedState dest=<null>

what=131221(0x20095)!CMD_IP_REACHABILITY_LOST

rt=210940/210940 FAILURE: LOST_PROVISIONING, NeighborEvent

{elapsedMs=210940, 192.168.1.1, [(null)], RTM_NEWNEIGH, NUD_FAILED}

或者搜索关键字" arp who-has" ,查看arp 是否有reply,delay高不高。

四. Datastall 触发

原理机制:

谷歌的一个在亮屏下一分钟检测一次网络状态的机制,一旦判定异常则会通知给CS。

什么情况下会被判定是异常即发生了datastall呢?

1. 过去一个poll 周期内丢包率达到了80%

/**

* Default tcp packets fail rate to suspect as a data stall.

*

* Calculated by ((# of packets lost)+(# of packets retrans))/(# of packets sent)*100. Ideally,

* the percentage should be 100%. However, the ongoing packets may not be considered as neither

* lost or retrans yet. It will cause the percentage lower.

*/

publicstaticfinal intDEFAULT_TCP_PACKETS_FAIL_PERCENTAGE = 80;

2. 半小时内DNS 失败达到5次

// Default configuration values for data stall detection.

publicstaticfinalintDEFAULT_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD = 5;

publicstaticfinalintDEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS = 30* 60* 1000;

driver日志中查看是否发生datastall,类似日志如下

13:44:35.605317 [ kworker/u16:10][ 0x96c51f025d][ 13:44:35.602210]wlan: [6253:D:WMA] Received reason code 6 from FW

13:44:35.605322 [ kworker/u16:10][ 0x96c51f032a][ 13:44:35.602220]wlan: [6253:D:WMA] Data Stall event:

13:44:35.605389 [ kworker/u16:10][ 0x96c51f038a][ 13:44:35.602225]wlan: [6253:D:WMA] data _stall_type: 3 vdev _id_bitmap: 1 reason _code1: 0 reason_code2: 7 recovery_type: 0

13:44:35.605397 [ kworker/u16:10][ 0x96c51f11a3][ 13:44:35.602413]wlan: [6253:D:QDF] cds _set_log _completion: 2136: is_fatal 1 indicator 3 reason_code 6 recovery needed 0

13:44:35.629190 [ wlan_logging_th][ 0x96c51fc43e][ 13:44:35.604795]wlan: [900:D:HDD] send _flush_completion _to_user: Sending flush done to userspace reason code 6

五. TX/RX 收发包异常

除了看是否datastall,我们还会查看TX/RX 数值变化,以此来判断当前网络是否正常。

//异常:RX的pkt cnt 涨幅很小,正常情况下是持续增长

15:04:57.822610 [ wifico][ 0x183a3b70779][ 15:04:57.369087]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450071, nss 2, bw 4]

15:05:00.379218 [ wifico][ 0x183a728afa9][ 15:05:00.378476]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450073, nss 2, bw 4]

15:05:03.686570 [ wifico][ 0x183aa9a651c][ 15:05:03.388042]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450074, nss 2, bw 4]

15:05:07.132915 [ wifico][ 0x183ae0eb713][ 15:05:06.406522]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450075, nss 2, bw 4]

15:05:09.422157 [ wifico][ 0x183b18213a7][ 15:05:09.421730]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450105, nss 2, bw 4]

15:05:13.535129 [ wifico][ 0x183b4f56b07][ 15:05:12.436868]wlan: [1372:D:HDD] wlan _hdd_get _sta_stats:

[TX: Reporting MCS rate 8, flags 0x14 pkt cnt 267148, nss 2, bw 4]-[RX: Reporting MCS rate 8, flags 0x14 pkt cnt 450107, nss 2, bw 4]

分析:

driver日志查看TX/RX 收发包是否正常,不正常的话则通过Sniffer 进一步分析是路由没转发还是底层收了没往上传。

六 . AP 侧异常

09-06 10:48:56.919 < 3> [ 1555.321037] (1)[ 3319:tx_thread][ wlan]

Rx Deauth frame from BSSID=[aa:63:df:5c:db:c5].

09-06 10:48:56.919 < 3> [ 1555.321093] (1)[ 3319:tx_thread][ wlan] Reason code = 7

除了上面这种AP 侧主动发起的掉线外,还有一些情况比如AP 侧更改了 security

2022 -02-1009 :31:32.092<4> [ 3273.328514]<2> (1) [4122:tx_thread]

[wlan]rsnCheckSecurityModeChanged: ( RSNINFO) securitychange, WPA2-> WEP

2022 -02-1009 :31:32.092<4> [ 3273.328530]<2> (1) [4122:tx_thread]

[wlan]scanProcessBeaconAndProbeResp: ( SCNINFO) Beaconsecuritymodechangedetected

2022 -02-1009 :31:32.092<4> [ 3273.328544]<2> (1) [4122:tx_thread]

[wlan]aisFsmStateAbort_NORMAL_TR: ( INITINFO) aisFsmStateAbort_NORMAL_TR

2022 -02-1009 :31:32.092<4> [ 3273.328559]<2> (1) [4122:tx_thread]

[wlan]aisFsmDisconnect: ( INITINFO) aisFsmDisconnect

3. 漫游问题

触发Roaming 最常见的原因是low rssi,除此之外,还有一些原因:

/* qcom* ROAM_TRIGGER_REASON_PER:

* Set if the roam has to be triggered based on a bad packet error rates (PER).

* ROAM_TRIGGER_REASON_BEACON_MISS:

* Set if the roam has to be triggered based on beacon misses from the connected AP.

* ROAM_TRIGGER_REASON_POOR_RSSI:

* Set if the roam has to be triggered due to poor RSSI of the connected AP.

* ROAM_TRIGGER_REASON_BETTER_RSSI:

* Set if the roam has to be triggered upon finding a BSSID with a better RSSI than the connected BSSID.

* Here the RSSI of the current BSSID need not be poor.

* ROAM_TRIGGER_REASON_PERIODIC:

* Set if the roam has to be triggered by triggering a periodic scan to find a better AP to roam.

* ROAM_TRIGGER_REASON_DENSE:

* Set if the roam has to be triggered when the connected channel environment is too noisy/congested.

* ROAM_TRIGGER_REASON_BTM:

* Set if the roam has to be triggered when BTM Request frame is received from the connected AP.

//.....

* ROAM_TRIGGER_REASON_DEAUTH:

* Set if the roam has to be triggered when device receives Deauthentication/Disassociation frame from connected AP.

* ROAM_TRIGGER_REASON_IDLE:

* Set if the roam has to be triggered when the device is in idle state (no TX/RX) and suspend mode, if the current RSSI is determined to be a poor one.

* ROAM_TRIGGER_REASON_TX_FAILURES:

* Set if the roam has to be triggered based on continuous TX Data frame failures to the connected AP.

* ROAM_TRIGGER_REASON_EXTERNAL_SCAN:

* Set if the roam has to be triggered based on the scan results obtained from an external scan (not triggered to aim roaming).

以其中比较常见的一种ROAM_TRIGGER_REASON_BEACON_MISS 为例(qcom)

# Set beacon missed count threshold

# if beacon missed counter > gRoamBmissFirstBcnt+gRoamBmissFinalBcnt,

# heartbeat error triggered

gRoamBmissFirstBcnt= 10

gRoamBmissFinalBcnt= 20

当某一次的beacon miss 次数超过gRoamBmissFirstBcnt+gRoamBmissFinalBcnt之和,则触发漫游,寻找合适的目标漫游热点,如果找不到候选者,则会断开网络。

//first_bmiss_detected=1 10个beacon miss

11:39:49.810713 R0: FWMSG: [2dd0beecbe] SWBMISS_TIMER_FN: vdev_id=0, curr_bmiss_bcnt=26, pre_bmiss_detected=1,

first_bmiss_detected=1, final_bmiss_detected=0, b_timeout=1, cons_bmiss_count = 61

11:39:49.834534 R0: FWMSG: [2dd0dcd3ef] SWBMISS_TIMER_FN: vdev_id=0, curr_bmiss_bcnt=27, pre_bmiss_detected=1, first_bmiss_detected=1, final_bmiss_detected=0, b_timeout=1, cons_bmiss_count = 62

11:39:49.835649 R0: FWMSG: [2dd0fb07a0] SWBMISS_TIMER_FN: vdev_id=0, curr_bmiss_bcnt=28, pre_bmiss_detected=1, first_bmiss_detected=1, final_bmiss_detected=0, b_timeout=1, cons_bmiss_count = 63

11:39:49.837121 R0: FWMSG: [2dd118f087] SWBMISS_TIMER_FN: vdev_id=0, curr_bmiss_bcnt=29, pre_bmiss_detected=1, first_bmiss_detected=1, final_bmiss_detected=0, b_timeout=1, cons_bmiss_count = 64

//final_bmiss_detected=1 在前面丢了10个beacon 的基础上又丢了20个beacon

11:39:49.837648 R0: FWMSG: [2dd11ed6b0] SWBMISS_NULL_SEND_CMPLT: vdev_id=0, isQosNullSuccess=0, isFinalBmiss=1, first_bmiss_detected=1,

final_bmiss_detected=1, fbmiss_evnt_posted=0, vbmiss->connected = 1, cons_bmiss_count = 65

11:39:49.838136 R0: FWMSG: [2dd11eda17] VDEV_MGR_FINAL_BMISS_DETECTED: vdev_id = 0

11:39:49.838657 R0: FWMSG: [2dd11ee1b0] ROAM_FINAL_BMISS_RECVD curr_rssi_avg = -68 dBm bcn_rssi_last = -68 dBm roam_scan_state(IDLE 0/ACTIVE_SCAN 1/ACTIVE_ROAM 2) = 0 scan_param.mode(5-7)/fina_scan(0-4) = 0x62 scan_status(bit3)/candidate_found(bit2)/send_beacon_to_host(bit1)/final_bmiss_recvd(bit0) = 0x06 is_qnull_fbmiss = 0

//触发漫游前的扫描

11:39:49.838724 R0: FWMSG: [2dd11ee4d5] ROAM_SCAN_REQUESTED send_beacon_to_host = 1 scan_type(FULL 0/CHANLIST 1/CHANMAP 2/FORCED 3/5G_ONLY 4) = 2 roam_scan_state (IDLE 0/ACTIVE_SCAN 1/ACTIVE_ROAM 2) = 0 final_scan = 1 num_chan = 13

11:39:49.838738 R0: FWMSG: [2dd11ee532] ROAM_FINAL_BMISS_SCAN scan_policy=0xf,skip_dfs=0,active_dwell=55 birst_dur=900

小结

至此,我们讨论了网络上几个有趣的问题,同时讨论了Android 平台上常见的WiFi 问题分析思路。本文由于受限于篇幅,加之笔者水平限制,相信会存在不足的地方,希望本文能够起到抛砖引玉的作用。

参考文献

https: //blog.csdn.net/shuyan1115/article/details/102476599

https: //juejin.cn/post/6844903986189844493

https: //blog.csdn.net/dog250/article/details/52548345

 

 

 

 

相关文章:

Android wifi常见问题及分析

参考 Android Network/WiFi 那些事儿 前言 本文将讨论几个有意思的网络问题&#xff0c;同时介绍 Android 上常见WiFi 问题的分析思路。 网络基础Q & A 一. 网络分层缘由 分层想必大家很熟悉&#xff0c;是否想过为何需要这样分层&#xff1f; 网上大多都是介绍每一层…...

如何用 ESP32-CAM 做一个实时视频流服务器

文章目录 ESP32-CAM 概述ESP32-S 处理器内存Camera 模块MicroSD 卡槽天线板载 LED 和闪光灯其他数据手册和原理图ESP32-CAM 功耗 ESP32-CAM 引脚参考引脚排列GPIO 引脚哪些 GPIO 可以安全使用&#xff1f;GPIO 0 引脚MicroSD 卡引脚 ESP32-CAM 的烧录方式使用 ESP32-CAM-MB 编程…...

编译与汇编

本文来自《程序员的自我修养》 编译过程是把预处理完的文件进行一系列词法分析&#xff0c;语法分析&#xff0c;语义分析以及优化后生成相应的汇编文件代码。 现在版本的GCC把预编译和编译两个步骤合并为一个步骤。 gcc -S HelloWorld.c HelloWorld.sint main() {//test/* …...

Linux入门攻坚——43、keepalived入门-1

Linux Cluster&#xff08;Linux集群的类型&#xff09;&#xff1a;LB、HA、HPC&#xff0c;分别是负载均衡集群、高可用性集群、高性能集群。 LB&#xff1a;lvs&#xff0c;nginx HA&#xff1a;keepalived&#xff0c;heartbeat&#xff0c;corosync&#xff0c;cman HP&am…...

备考蓝桥杯:顺序表相关算法题

目录 询问学号 寄包柜 移动0 颜色分类 合并两个有序数组 物品移动 询问学号 我们的思路&#xff1a;创建一个顺序表存储从1开始依次存放进入教室的学生学号&#xff0c;然后查询 #include <iostream> #include <vector> using namespace std; const int N 2…...

【STM32+QT项目】基于STM32与QT的智慧粮仓环境监测与管理系统设计(完整工程资料源码)

视频演示: 基于STM32与QT的智慧粮仓环境监测与管理系统设计 目录: 目录 视频演示: 目录: 前言:...

Vue3 自定义hook

文章目录 Vue3 自定义hook概述用法 Vue3 自定义hook 概述 Vue3推荐利用Vue的组合式API函数进行代码封装&#xff0c;这种封装方式统称为自定义hook。 用法 定义 hook/countHook.js&#xff1a; import {computed, ref, watch} from "vue";export default (initC…...

【VBA】【EXCEL】将某列内容横向粘贴到指定行

Sub CopyRowToColumn()On Error GoTo ErrorHandler 添加错误处理Application.ScreenUpdating FalseApplication.Calculation xlCalculationManualApplication.EnableEvents False 禁用事件处理Dim lastCol As LongDim lastRow As LongDim i As Long, colCount As LongDim …...

使用Llama 3.1创建合成数据集以调优你的大型语言模型

使用Llama 3.1创建合成数据集以调优你的大型语言模型 在数据驱动的人工智能领域&#xff0c;数据是核心资产。开发高质量数据集既复杂又昂贵&#xff0c;因此很多实验室和开发者选择使用合成数据集。本文将介绍如何利用大型语言模型Llama 3.1 405B创建合成数据集&#xff0c;并…...

【Ubuntu22.04】VMware虚拟机硬盘扩容

1.首先打开虚拟机设置 2.根据需要对硬盘扩展 这边提示我们还需要进入虚拟机在内部分区 3.安装界面化磁盘管理工具 # 安装 sudo apt install gparted# 启动 sudo gparted调整硬盘大小 调整的时候会提示我们硬盘是只读的&#xff0c;因此还要进行操作 新建终端重新挂载文件系…...

初学stm32 --- DMA直接存储器

目录 DMA介绍 STM32F1 DMA框图 DMA处理过程 DMA通道 DMA优先级 DMA相关寄存器介绍 F1 DMA通道x配置寄存器&#xff08;DMA_CCRx&#xff09; DMA中断状态寄存器&#xff08;DMA_ISR&#xff09; DMA中断标志清除寄存器&#xff08;DMA_IFCR&#xff09; DMA通道x传输…...

reactor中的并发

1. reactor中的并发有两种方式 1.1 flatmap&#xff0c;底层是多线程并发处理。在reactor的演讲中&#xff0c;flatmap对于io类型的并发效果较好. flamap有两个参数: int concurrency, int prefetch。分别代表并发的线程数和缓存大小 注意凡是参数中有prefetch的&#xff0c;都…...

HTML - <script>,<noscript>

<script>标签用于在网页插入脚本&#xff0c;<noscript>标签用于指定浏览器不支持脚本时的显示内容。 1.<script> <script>用于加载脚本代码&#xff0c;目前主要是加载 JavaScript 代码。 <script> console.log(hello world); </script&g…...

C#语言的函数实现

C#语言的函数实现 在现代编程语言中&#xff0c;函数&#xff08;Function&#xff09;是最基本也是最重要的组成部分之一。函数不仅提高了代码的复用性&#xff0c;还使得程序结构更清晰。C#作为一种多用途的编程语言&#xff0c;函数的知识是程序员必备的基本技能之一。本文…...

JAVA I/O流练习1

往D盘中的JAVA复习文件夹中写数据&#xff1a; 数据改了一下哈&#xff1a; import java.io.*; import java.util.Scanner; public class Test {public static void main(String[] args) throws IOException {String fileName"D:JAVA复习\\grade.txt";FileWriter w…...

HTML——75. 内联框架

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>内联框架</title><style type"text/css">iframe{width: 100%;height: 500px;}</style></head><body><!--iframe元素会创建包含…...

js获取当前浏览器地址,ip,端口号等等

前言&#xff1a; js获取当前浏览器地址&#xff0c;ip&#xff0c;端口号等等 window.location属性查询 具体属性&#xff1a; 1、获取他的ip地址 window.location.hostname 2、获取他的端口号 window.location.port 3、获取他的全路径 window.location.origin 4、获取…...

C++虚函数(八股总结)

什么是虚函数 虚函数是在父类中定义的一种特殊类型的函数&#xff0c;允许子类重写该函数以适应其自身需求。虚函数的调用取决于对象的实际类型&#xff0c;而不是指针或引用类型。通过将函数声明为虚函数&#xff0c;可以使继承层次结构中的每个子类都能够使用其自己的实现&a…...

【每日学点鸿蒙知识】跳转三方地图、getStringSync性能、键盘避让模式等

1、跳转三方地图导航页 类似于Android 跳转到地图APP 导航页面&#xff1a; // 目标地点的经纬度和名称 double destinationLat 36.547901; double destinationLon 104.258354; String destinationName "目的地名称"; // 构建URI Uri uri Uri.parse("…...

【线性代数】通俗理解特征向量与特征值

这一块在线性代数中属于重点且较难理解的内容&#xff0c;下面仅个人学习过程中的体会&#xff0c;错误之处欢迎指出&#xff0c;有更简洁易懂的理解方式也欢迎留言学习。 文章目录 概念计算几何直观理解意义 概念 矩阵本身就是一个线性变换&#xff0c;对一个空间中的向量应用…...

C#设计模式(行为型模式):备忘录模式,时光倒流的魔法

C#设计模式&#xff1a;备忘录模式&#xff0c;时光倒流的魔法 在软件开发中&#xff0c;我们经常会遇到需要保存对象状态&#xff0c;并在未来某个时刻恢复的场景。例如&#xff1a; 撤销操作&#xff1a; 文本编辑器中的撤销功能&#xff0c;游戏中的回退操作。事务回滚&am…...

服务器信息整理:用途、操作系统安装日期、设备序列化、IP、MAC地址、BIOS时间、系统

文章目录 引言I BIOS时间Windows查看BIOS版本安装日期linux查看BIOS时间II 操作系统安装日期LinuxWindowsIII MAC 地址IV 设备序列号Linux 查看主板信息知识扩展Linux常用命令引言 信息内容:重点信息:用途、操作系统安装日期、设备序列化、IP、MAC地址、BIOS时间、系统 Linux…...

用OpenCV实现UVC视频分屏

分屏 OpencvUVC代码验证后话 用OpenCV实现UVC摄像头的视频分屏。 Opencv opencv里有很多视频图像的处理功能。 UVC Usb 视频类&#xff0c;免驱动的。视频流格式有MJPG和YUY2。MJPG是RGB三色通道的。要对三通道进行分屏显示。 代码 import cv2 import numpy as np video …...

【C#学习】基类的静态变量 派生类会如何处理

来源GPT&#xff0c;仅记录学习 在C#中&#xff0c;子类继承父类的public static变量时&#xff0c;父类的静态变量对所有类&#xff08;包括子类&#xff09;都是共享的。子类并不会重新创建父类静态变量&#xff0c;而是共享父类的静态成员。 具体行为&#xff1a; 静态变量…...

Unity3D仿星露谷物语开发19之库存栏丢弃及交互道具

1、目标 从库存栏中把道具拖到游戏场景中&#xff0c;库存栏中道具数相应做减法或者删除道具。同时在库存栏中可以交换两个道具的位置。 2、UIInventorySlot设置Raycast属性 在UIInventorySlot中&#xff0c;我们只希望最外层的UIInventorySlot响应Raycast&#xff0c;他下面…...

SQL进阶实战技巧:如何利用 Oracle SQL计算线性回归置信区间?

目录 1 置信区间计算方法 步骤1:计算回归系数 步骤2:计算标准误差 步骤3:计算置信区间 2 数据准备 <...

计算机网络——网络层—IP数据报与分片

一、IP 数据报的格式 • 一个 IP 数据报由首部和数据两部分组成。 • 首部的前一部分是固定长度&#xff0c;共 20 字节&#xff0c;是所有 IP 数据报必须具有的。 • 在首部的固定部分的后面是一些可选字段&#xff0c;其长度是可变的。 IP 数据报首部的固定部分中的各字段 版…...

高山旅游景区有效降低成本,无人机山下到山上物资吊运技术详解

在高山旅游景区&#xff0c;传统的物资运输方式往往面临人力成本高昂、效率低下等问题&#xff0c;而无人机技术的引入为这一难题提供了新的解决方案。以下是对无人机从山下到山上进行物资吊运技术的详细解析&#xff1a; 一、无人机物资吊运技术的优势 1. 降低人力成本&#…...

Linux 注册线程化的中断处理程序

1. 注册线程化中断处理函数 devmem_request_threaded_irq 是 Linux 内核中的一个函数&#xff0c;用于请求并注册一个线程化的中断处理程序。这个函数允许开发者注册一个中断处理函数&#xff0c;这个函数会在中断发生时被调用&#xff0c;从而实现相应的中断处理逻辑。它通过…...

【狂热算法篇】解锁数据潜能:探秘前沿 LIS 算法

嘿&#xff0c;各位编程爱好者们&#xff01;今天带来的 LIS 算法简直太赞啦 无论你是刚入门的小白&#xff0c;还是经验丰富的大神&#xff0c;都能从这里找到算法的奇妙之处哦&#xff01;这里不仅有清晰易懂的 C 代码实现&#xff0c;还有超详细的算法讲解&#xff0c;让你轻…...

Linux: 关于 mount 的一些细节

文章目录 1. 前言2. mount 的主要细节 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. mount 的主要细节 mount 从系统调用 sys_mount() 发起&#xff0c;如 mount -t tmpfs cgroup /sys/fs/cg…...

CSS3——3. 书写格式二

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><!--css书写&#xff1a;--><!--1. 属性名:属性值--><!--2.属性值是对属性的相关描述--><!--3.属性名必须是…...

Java-JVM详解

Java-JVM ①JVM概述 ❶基本介绍 JVM&#xff1a;全称 Java Virtual Machine&#xff0c;一个虚拟计算机&#xff0c;Java 程序的运行环境&#xff08;Java二进制字节码的运行环境&#xff09; 特点&#xff1a; Java 虚拟机基于二进制字节码执行&#xff0c;由一套字节码指…...

docker搭建atlassian-confluence:7.2.0

文章目录 引言I 部署前准备数据库镜像准备自己构建镜像dockerhub第三方镜像II 安装启动容器基础配置(获取服务器ID)授权码获取集群选择设置数据库配置管理员账号引言 准备数据库、镜像启动容器获取服务器ID根据服务器ID等信息,基于atlassian-agent.jar 授权I 部署前准备 数…...

YOLOv8实战人员跌倒检测

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对人员跌倒目标数据集进行训练和优化&#xff0c;该数据集包含丰富人员跌倒图像样…...

瑞芯微rk3568平台 openwrt系统适配ffmpeg硬件解码(rkmpp)

瑞芯微rk3568平台 openwrt系统适配ffmpeg硬件解码(rkmpp) RK3568及rkmpp介绍编译安装mpp获取源码交叉编译安装 libdrmlibdrm-2.4.89 make 方式编译(cannot find -lcairo, 不推荐)下载源码编译编译错误: multiple definition of `nouveau debug‘错误cannot find -lcairo:…...

自动驾驶控制与规划——Project 6: A* Route Planning

目录 零、任务介绍一、算法原理1.1 A* Algorithm1.2 启发函数 二、代码实现三、结果分析四、效果展示4.1 Dijkstra距离4.2 Manhatten距离4.3 欧几里德距离4.4 对角距离 五、后记 零、任务介绍 carla-ros-bridge/src/ros-bridge/carla_shenlan_projects/carla_shenlan_a_star_p…...

wordpress报错open_basedir restriction in effect

Warning: file_exists(): open_basedir restriction in effect. File(/www/wwwroot/wp-content/plugins/woocommerce/patterns/banner.php) is not within the allowed path(s): 关闭防跨站攻击...

VSCode Live Server 插件安装和使用

VSCode Live Server是一个由Ritwick Dey开发的Visual Studio Code扩展插件&#xff0c;它提供了一个带有实时重载功能的本地开发服务器。在VSCode中安装和使用Live Server插件进行实时预览和调试Web应用程序。这将大大提高前端开发效率&#xff0c;使网页设计和开发变得更为流畅…...

网络安全-XSS跨站脚本攻击(基础篇)

漏洞扫描的原理 1.跨站脚本攻击介绍 xss跨站脚本攻击&#xff1a; xSS 全称&#xff08;Cross site Scripting &#xff09;跨站脚本攻击&#xff0c;是最常见的Web应用程序安全漏洞之一&#xff0c;位于OWASP top 10 2013/2017年度分别为第三名和第七名&#xff0c;XSS是指攻…...

【C++笔记】红黑树(RBTree)深度剖析和AVL树的对比分析

【C笔记】红黑树(RBTree)深度剖析和AVL树的对比分析 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】红黑树(RBTree)深度剖析和AVL树的对比分析前言一.红黑树的定义1.1 红黑树的概念1.2红黑树的规则1.3 红黑树对比A…...

Mysql 性能优化:索引条件下推(ICP)

MySQL 索引下推&#xff08;Index Condition Pushdown&#xff0c;ICP&#xff09;是一种查询优化技术&#xff0c;旨在提高使用索引的查询效率。它是在 MySQL 5.6 中引入的&#xff0c;通过将部分 WHERE 子句的过滤条件下推到索引扫描阶段来减少不必要的回表操作&#xff0c;从…...

docker如何进入交互模式

目录 使用 docker run -it 使用 docker exec -it 示例&#xff1a; 使用 docker attach 示例&#xff1a; 在写代码的时候对小白来说避免不了本地和docker环境执行结果不一样的情况 这个时候需要进入正在运行的容器进行调试或执行一些命令操作。这时可以使用 Docker 提供的…...

闲谭SpringBoot--ShardingSphere分库分表探究

文章目录 1. 背景2. 创建数据库3. 修改yml配置文件4. 分片算法类5. 测试6 小结 1. 背景 接上文&#xff0c;我们对日志表&#xff0c;进行了按月的分表&#xff0c;这样每个月几百万条数据量还是扛得住的。 但是如果数据再多呢&#xff0c;除了提高硬件性能&#xff0c;还有一…...

在Java中Semaphore的解释及主要用途

目录 定义 使用方法 主要用途 使用场景示例 定义 Semaphore&#xff08;信号量&#xff09;是Java并发编程中的一个同步工具类&#xff0c;用于控制对共享资源的访问。它通过维护一个计数器来管理多个线程对资源的并发访问数量。这个计数器表示当前可用的许可数&#xff0c…...

React Native 项目 Error: EMFILE: too many open files, watch

硬件&#xff1a;MacBook Pro (Retina, 13-inch, Mid 2014) OS版本&#xff1a;MacOS BigSur 11.7.10 (20G1427) 更新: 删除modules的方法会有反弹&#xff0c;最后还是手动安装了预编译版本的watchman。 React Native 项目运行npm run web&#xff0c;出现如下错误&#xff1a…...

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git&#xff0c;就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …...

5 分布式ID

这里讲一个比较常用的分布式防重复的ID生成策略&#xff0c;雪花算法 一个用户体量比较大的分布式系统必然伴随着分表分库&#xff0c;分机房部署&#xff0c;单体的部署方式肯定是承载不了这么大的体量。 雪花算法的结构说明 如下图所示: 雪花算法组成 从上图我们可以看…...

flink的EventTime和Watermark

时间机制 Flink中的时间机制主要用在判断是否触发时间窗口window的计算。 在Flink中有三种时间概念&#xff1a;ProcessTime、IngestionTime、EventTime。 ProcessTime&#xff1a;是在数据抵达算子产生的时间&#xff08;Flink默认使用ProcessTime&#xff09; IngestionT…...

T-SQL语言的函数实现

T-SQL语言的函数实现 在数据库管理系统中&#xff0c;函数是一种非常重要的编程结构。SQL Server支持多种类型的函数&#xff0c;包括标量函数、表值函数和系统函数。本文将详细介绍T-SQL中函数的实现&#xff0c;结合实际应用场景&#xff0c;帮助读者深入理解函数的使用方法…...