手机是怎么搜到附近WiFi的?路由器每0.1秒报一次名,你刷的列表全是手机问出来的

上个月出差住酒店,前台小妹把WiFi名报得飞快,我掏出手机点开WLAN开关,转了一秒多,列表里齐刷刷蹦出五六个名字。当时我旁边一位大哥等得直嘀咕:这玩意儿是从哪搜出来的?
回来路上我抓包看了一遍才想明白,那张列表不是手机单方面「搜」的,是手机和路由器配合演出来的:路由器一直在后台报家门,手机在那一两秒里把所有信道挨个问了一遍。两边各干一半的活,缺一个你都刷不出列表。
先说清楚:那张列表是「听」出来加「问」出来的
WiFi的发现就两条路,教科书上叫被动扫描和主动扫描,翻译成人话就是「听」和「问」。
被动扫描是纯听。路由器只要通着电,就会每隔大约0.1秒朝空气里广播一个小包,叫beacon帧,中文叫信标帧。这包不发给别人,就发给所有人和没人,谁收到谁知道。手机趴在一个信道上不动,等着收这个包,收到了就等于知道了「这信道上有个叫ChinaNet-xxyy的路由器」。
主动扫描是主动问。手机切到一个信道,先朝空气里喊一嗓子「这信道上谁在?」,这个喊话的包叫probe request,探测请求。周围的路由器听见了就回一句「我在,我叫什么什么,我支持什么速率」,这句回话叫probe response。问一句答一句,比干等着听快得多。
你手机点开列表的那一两秒,走的基本都是主动扫描这条路。所以严格说,WiFi列表不是「搜」出来的,是手机挨家挨户敲门问出来的,路由器平时广播的信标帧更多是给「守株待兔」的设备留的后手。
路由器那一嗓子:beacon帧里装着WiFi的户口本
路由器广播信标帧的默认间隔是100个TU。TU是WiFi标准里的时间单位,1个TU等于1024微秒,100个TU算下来约102.4毫秒。也就是说路由器每秒要朝空气里喊差不多10次「我叫这个名字」,一天下来八十六万多嗓子,全年无休。
这一嗓子里装的东西,基本就是这个WiFi的户口本:
| 字段 | 装的是什么 | 你看到的现象 |
| 名字 | SSID,WiFi的名称 | 列表里那一行字 |
| 信道和频段 | 工作在哪个信道 | 手机知道该去哪个信道连 |
| 支持的速率 | 从低到高一串速率档位 | 信号差时知道能降到多低 |
| 加密方式 | WPA2还是WPA3 | 输密码页面上那行小字 |
| 能力信息 | 是不是WiFi6、带不带Mesh | 列表名字旁边那个6的角标 |
| 省电标记 | 有没有给休眠设备的暂存包 | 锁屏后消息还能不能及时到 |
还有一件事也归它管:列表里的信号格数。路由器每0.1秒喊一次,手机每次都能顺手量一下这个包到达时的信号强度,量出来的就是那个负几十的dBm读数,格数只是把它换算成了四格五格。之前写信号那篇我提过-60以内随便用、过-70就没啥幻想,那一串判断的原始数据,全是从beacon帧上一个包一个包量出来的。家里哪个角落信号弱,抱着手机走一圈,走的其实是「边走边收信标帧」的测量,这法子我在盲区自查那篇里写过。
手机那两秒在忙什么:把二十来个信道挨个跳一遍
主动扫描听着快,也得一个信道一个信道来。2.4G频段一共13个信道,5G频段咱们国内常用的又有13个上下,加起来二十多个。手机不能同时蹲所有信道,只能跳着扫:切到信道1,喊一嗓子,听回答,切到信道6,再喊,再听,一路跳完。
在每个信道上停留多久有讲究。标准里给了两个数:最短等待时间大约10到20毫秒,最长等待时间大约100毫秒。手机喊完那一嗓子先按最短的等,这段时间里静悄悄没人应答,说明这信道上没路由器,扭头就走,一毫秒都不多待;要是有人应了第一声,就按最长的等,把这一信道上所有路由器的回答都收齐了再走。
这么一算账就明白了:空信道多的时候扫得快,路由器密的时候扫得慢。我住的酒店那一层隔壁就是商场,2.4G的13个信道几乎个个有人,每个信道都要等满约100毫秒,光2.4G一轮就一秒多,加上5G那十几个信道,列表刷新要等两秒很正常。你要是住的老小区,邻居的路由器把2.4G挤得满满当当,可以看看我写蓝牙和WiFi挤2.4G那篇,那场面就是十几个路由器每秒各喊十嗓子,空气里相当热闹。
顺带说一句,5G频段为什么列表里后出来、有时候还搜不全,也是这个原因。5G信道数跟2.4G差不多,但5G信号衰减快,隔两堵墙很多路由器的喊话就弱得听不清了,手机得多轮才能确认。频段本身的差别我在这篇2.4G和5G怎么选里实测过,这里不重复。
隐藏WiFi为什么拦不住人:不报名字,但问对了还是答
说到这就能把一个老问题讲透了:隐藏SSID的路由器,beacon帧照样每0.1秒发一次,只是名字那一栏空着。手机列表扫一圈,收到的是一个「有个WiFi但我不知道叫啥」的包,列表上自然不显示。
但主动扫描留了一扇门。手机发的探测请求里可以带上名字问:「叫XXX的你在这吗?」隐藏的路由器一听问的是自己的名字,就会回答。所以隐藏WiFi的手动添加功能,本质上就是手机替你喊对了那句暗号。这也是我说隐藏防不住行家的原因,抓包工具守在旁边,等任何一台连过的设备把名字喊出来,底就漏了。真想干净,改长密码比隐藏有用得多,这个账我在隐藏WiFi那篇里算过。
beacon还管手机省电:DTIM这个数字改大改小的账
信标帧里还有个不起眼的字段,管着手机锁屏后的耗电,叫DTIM。手机连上WiFi后并不一直竖着耳朵听,锁屏后会打盹,隔一阵醒一次,看看路由器最新的信标帧里有没有给自己暂存的消息。醒来这个周期就是DTIM,多数路由器默认是1或3,意思是每1个或每3个信标周期醒一次。
这个数改大,手机睡得更沉更省电,一些老路由器把它从1调到3,手机待机能多撑小半天。但有代价:路由器暂存的组播包要等手机醒来才发。投屏发现、打印机自动发现这类靠组播撑着的活,DTIM调太大就会变得迟钝甚至失灵,组播是干嘛的我在这篇组播原理里写过。家用路由器的后台一般把这个藏得很深,OpenWrt这类固件里才能直接改,我的建议是不折腾,默认值是厂商算好的平衡点。
信标间隔本身也一样能调,从100毫秒改成200毫秒,空气里的开销减半,路由器自己那点电也省了,但手机发现新网络更慢、漫游切换的判断也更迟钝。除非你家信道挤到爆炸,否则这俩参数都别动。
知道这套机制,三个实际问题自己就能判断
第一个:列表空白,一个WiFi都搜不出来。先别怀疑手机坏了,安卓手机扫描WiFi跟读取WiFi信息绑在一起,被划进了定位相关权限,不开定位,系统干脆让扫描返回空结果。这个坑跟智能设备配网要开定位是同一套逻辑,我在配网那篇里详细写过。开完定位再刷新,多数就出来了。
第二个:列表刷新不出来新名字。系统对App滥用扫描是有节流的,前台应用短时间内反复请求扫描会被系统直接拒掉,老版本安卓两分钟里也就给你扫四次。你手动在设置里关开WLAN开关,属于系统自己的操作,不受这个限制。所以「列表不更新」先关开一次开关,比反复下拉有用。
第三个:列表里的名字都见了,可连上以后转圈上不了网。那是另一码事了,手机判断「有没有网」靠的是偷偷访问一个探针网址,跟扫描列表没关系,这套判断机制我拆过,在这篇连上WiFi却提示无法上网里。
收尾给个对号表:
| 现象 | 病根在哪 | 第一动作 |
| 列表完全空白 | 定位权限把扫描拦了 | 开定位,再关开一次WLAN |
| 列表要一两秒才齐 | 二十多个信道挨个问,正常 | 不用管 |
| 某个WiFi时有时无 | 信号在可用边缘晃 | 看dBm读数,过-70别恋战 |
| 隐藏WiFi搜不到 | 信标帧不带名字 | 手动添加,输对名字 |
| 锁屏后消息延迟 | 省电周期没赶上组播 | DTIM别调大,恢复默认 |
一张WiFi列表背后,是路由器每秒十次的报家门和手机二十多个信道的挨家挨户敲门。下次在酒店等列表刷新,那两秒里手机正忙得很,稍微等等它。
