"客户反馈内网传大文件速度上不去,我让他顺手在网卡上抓了20秒流量。文件拿回来,我连数据包的Payload都没细看,先打开Statistics菜单里的Packet Lengths扫了一眼长度分布,问题就猜了个七八成——满屏全是54字节左右的纯ACK小包,真正携带数据的大包少得可怜。这不是个例,很多人学Wireshark一直执着于"读懂每个字段",反而忽略了统计这个最能直接出结论、最省时间的功能入口。
这篇文章就专门聊数据包长度统计这件事:怎么抓包、怎么用Wireshark把"发送的数据包长度"统计出来、统计结果又能怎么用于排障。适合两类人看,一类是刚装好Wireshark、拿到抓包文件不知道怎么提炼结论的新手;另一类是已经会基本过滤、但没怎么认真研究过Statistics菜单的进阶用户。核心就一个目标:让你下次打开任何一个pcap文件,能在一分钟内说出"这条链路上到底在跑什么东西、跑得对不对"。
1. 为什么关心数据包长度:从"抓包"到"读包"
1.1 长度是数据包的第一张"身份证"
在Wireshark的抓包列表里,有一个默认就存在的Length列,每一行数据包后面都会跟着一个数字。这个数字看着不起眼,但它是这个包最直观的指纹。一个包是来握手的、来传数据的、还是来刷存在的,长度值基本能直接告诉你。
举个例子,一个标准的TCP纯ACK包,抓包里通常显示54字节左右;一个从网卡发出的满尺寸数据包,在MTU为1500的以太网上通常是1514字节;一段最常见的G.711语音流里的RTP包,固定就是214字节上下。这些数字不需要看协议树,扫一眼就能辨识出来。
所以数据包长度统计本质上是在回答三个问题:链路上有多少个包?这些包都多大?大小分布是否合理?这三个问题展开之后,就能顺藤摸瓜找到很多网络故障的根因。
1.2 一个完整的以太网帧到底由什么组成
要理解长度,先得知道Wireshark里那个Length数值是怎么算出来的。以太网帧在抓包里看到的结构大致是:目的MAC地址6字节、源MAC地址6字节、类型字段2字节,后面才是真正的网络层数据。也就是说,Wireshark显示的frame.len,默认等于14字节的以太网头部加上后面的IP包长度。
正常情况下,标准以太网的MTU是1500字节,所以一个满帧的IP包最多1500字节,加上14字节的以太网头,Wireshark里看到的满帧就是1514字节。如果链路上带了VLAN标签,会额外多4字节,变成1518字节。如果开启了巨型帧(Jumbo Frame),帧长可以超过1514,常见的能到9000字节——你抓到一个2090字节的包,基本就是在巨型帧环境里,或者某些网卡和交换机对帧长做了特殊放行。
还需要区分两个容易混淆的字段:frame.len是原始帧长度,frame.cap_len是实际捕获到的长度。这两个值一旦不相等,说明包被截断了,后面第6节会详细说这个坑。
1.3 不同长度区间对应的"身份画像"
把抓包文件里的长度分布拉出来看,每个区间都有比较典型的代表:
| 长度区间(Wireshark显示值) | 典型协议/场景 | 说明 |
|---|---|---|
| 54 ~ 66 | TCP控制包(ACK、SYN、FIN) | 不带数据或只带极少选项 |
| 62 ~ 74 | TCP SYN握手包 | 通常带MSS、窗口缩放、时间戳等选项 |
| 70 ~ 90 | DNS查询、少量ICMP | 头部开销占比高 |
| 100 ~ 300 | HTTP请求、TLS握手、业务小包 | 常见于应用层控制交互 |
| 210 ~ 220 | VoIP语音包(G.711) | 每20毫秒一个,规律性极强 |
| 1280 ~ 1514 | 接近MTU的数据包 | 大批量文件传输时占比高 |
这个表是我平时判断流量的一个重要坐标。看到分布图我脑子里基本能浮现出这链路的业务画面:如果一大半是54字节的小包,说明控制类或无效流量太多;如果几乎全是1514的大包,那多半是文件下载、视频流这类大吞吐业务。
2. 抓包实操:拿到一份能说明问题的样本
2.1 选对网卡,别抓了个寂寞
统计结果准不准,第一步取决于抓包样本靠不靠谱。打开Wireshark,先看一眼主界面的网卡列表。Windows上用ipconfig、Linux上用ip addr show,先确认哪个网卡是真正承载业务的。
最容易犯的错是选了Loopback回环网卡,结果抓到一堆空包,或者干脆选了虚拟网卡,业务流量根本不走那里。如果你要抓的是访问外网的流量,就选有公网地址或走默认网关的那块物理网卡;抓内网服务器之间的流量,选接内网的那块网卡。
还有一个细节:默认情况下Wireshark会打开混杂模式(Promiscuous Mode),也就是网卡不只收目标为自己MAC地址的包,而是把线路上能看到的包都收进来。这个选项一定要保持开启,尤其你抓的是交换机镜像口或者Wi-Fi探针流量时,关了它可能什么都抓不到。
2.2 抓包选项里最容易埋雷的snaplen
点工具栏的齿轮图标进入Capture Options,里面有一个"Limit each packet to"选项,这就是snaplen(抓包截断长度)设置。Wireshark默认是65535字节,基本等于不限制,因为正常以太网帧最大也就9000多字节。
但如果你把这里改成了520,就会出现一个很经典的怪现象:每个包都只抓到前520字节,后面的内容全部丢失。Wireshark会在Info列提示"Packet size limited during capture",协议树里很多字段解析不出来,一长串数据全变成了"Data"的残缺内容。后面第6节我会专门讲怎么排查和修复。
这里顺便说个原则:做长度统计之前,先确认snaplen没有被改小。否则你统计出来的分布是被截断过的,尤其大包会集体"缩水",看起来全是小额数据包,容易误判。
2.3 用显示过滤器把目标流量剥出来
抓包全程可以在Capture Options里设置抓包过滤器(Capture Filter),语法是BPF那套,比如host 192.168.1.100 and tcp port 443,只保留和某个IP的443端口相关的包。这种过滤器在抓包阶段就丢弃不关心的流量,能大幅减小文件体积。
但抓包过滤器有个局限:它不认识frame.len这种Wireshark上层字段。真要按长度统计和过滤,得用抓完之后的显示过滤器(Display Filter)。比如:
frame.len > 1400:只看大包frame.len < 80:只看小包tcp.len > 0:只看TCP里真正带数据的包tcp.len == 0:只看TCP纯ACK这类无载荷包frame.cap_len < frame.len:直接找出被截断的包
记住这个区别很关键。很多人拿着frame.len > 1400往抓包过滤器里填,结果报错,就是因为用错了地方。
2.4 实操:完整抓取一次文件下载
我以最常见的HTTP大文件下载为例,走一遍标准流程:
- 先确认网卡,记录本机IP,比如192.168.1.100;
- 打开Capture Options,选择正确的网卡,把snaplen保持在65535;
- 为了减少干扰,可以加一条抓包过滤器
host 192.168.1.100,只看和本机相关的流量; - 点击Start开始抓包;
- 用curl或浏览器请求一个大文件,比如
curl -o /dev/null http://example.com/large-file.bin; - 下载结束后停止抓包,保存为download.pcapng。
这份文件里就包含了TCP三次握手、HTTP请求、大量1514字节的数据包、以及回程的ACK小包。用它来做长度统计,正好能看到一个典型下载业务的全貌:从握手小包,到请求小包,再到满负荷数据大包,最后到结束断开的小包。
3. 用Wireshark自带统计功能看长度分布
3.1 Statistics > Packet Lengths 逐个区间读懂
对刚保存的download.pcapng,打开Statistics菜单,点击Packet Lengths,会弹出按长度区间统计的表格。Wireshark自动把长度分成类似40到79、80到159、160到319、320到639、640到1279、1280到2559这样翻倍的区间,每行显示包数和占比。
这份数据是最直接的结论来源。一次典型的HTTP大文件下载,分布大概长这样:
| 长度区间 | 包数 | 占比 | 可能的角色 |
|---|---|---|---|
| 40 ~ 79 | 1850 | 30% | 三次握手、纯ACK回包 |
| 80 ~ 159 | 120 | 2% | HTTP请求、TLS握手 |
| 160 ~ 319 | 60 | 1% | 个别控制包 |
| 640 ~ 1279 | 350 | 5.6% | 中尺寸数据块 |
| 1280 ~ 2559 | 3800 | 61% | 接近MTU的数据包 |
看到这个分布,脑子里就能浮现画面:一半以上的包是满尺寸数据包,说明发送方在努力用大块数据填充链路;三成是ACK,是因为接收方每收到一批数据都要确认;整体大包占比越高,链路利用率通常越高。
这个对话框底部有Copy按钮,可以直接把统计表格复制成CSV,方便贴进汇报文档或者Excel里二次加工。
3.2 结合过滤器做定向统计:只看发送方向
很多时候我们不关心全部流量,只想统计"某个IP发送的数据包长度"。做法很简单:在显示过滤器里填ip.src == 192.168.1.100,然后再打开Packet Lengths,此时统计的就是从这个IP发出去的所有包。
如果想再进一步,只统计"这个IP发送且真正携带TCP数据的包",过滤条件改成ip.src == 192.168.1.100 and tcp.len > 0。这组数据才是真正体现发送吞吐能力的指标。比如一个服务器IP,如果它发出的包里90%都是纯ACK,说明它一直在被动响应别人,本身没有多少数据要传。
这里分享一个顺手的小技巧:在Packet Lengths对话框打开的状态下直接改显示过滤器,对话框里的数据会实时刷新,不用来回开关。我排障时经常把过滤器和统计窗口并排操作,效率高很多。
3.3 Conversations与Endpoints:谁在发大包,谁在发小包
Packet Lengths看的是全局分布,如果要细化到"哪台主机、哪对连接在发什么长度的包",就要看Statistics里的Conversations和Endpoints。
Endpoints会按IP或MAC地址汇总每个端点的发包数、收包数、发送字节数、接收字节数。比如你先发现整个抓包里某个IP的发送字节数是别人的100倍,那基本确认它就是流量大户。点一下Bytes列排序,谁是罪魁祸首一目了然。
Conversations则按通信双方IP加端口维度做汇总,能看到一条TCP连接的包数和字节数。比如下载任务里,服务器和客户端之间的那条连接字节数会高得吓人;如果是某个后台服务在疯狂轮询,那连接数量虽多,但每条连接的字节数都很小。做长度统计时,先用Conversations锁定可疑连接,再右键选择"Apply as Filter",就能只看这条连接的包,然后回到Packet Lengths看它的长度分布。
3.4 IO Graph:长度变化趋势一眼看穿
Packet Lengths是一张静态快照,IO Graph则能看到时间维度的变化。打开Statistics > IO Graph,默认横轴是时间,纵轴是包速率。这里有两个很有价值的玩法。
第一个玩法:把Y轴单位从Packets改成Bytes,立刻能看出某个时间段内的字节吞吐。如果曲线在某个时间点突然断崖式下跌,结合前后的包长度分布,能判断是数据包变小了还是包数量变少了,两种情况的排障方向完全不同。
第二个玩法:添加两条额外的图形线,一条的过滤条件填frame.len > 1400,另一条填frame.len < 80。这样一条线代表"大包流量",另一条代表"小包流量"。当两条线出现背离时,比如大包线往下掉、小包线反而往上窜,基本可以断定是出现了大量ACK或重传这类控制流量,业务数据却在饿肚子。
4. 更精细的统计:tshark与自定义列
4.1 什么时候需要离开图形界面
Wireshark图形界面很直观,但有两个场景它会显得笨重:一是PCAP文件非常多,几十个文件挨个点Statistics菜单能点到手酸;二是服务器上根本没有图形环境,只有tshark命令行工具可以用。
tshark是Wireshark自带的命令行版本,装Wireshark的时候会一起装好。它能对PCAP做批处理统计,还能写出带精确条件的过滤逻辑,非常适合沉淀成脚本定期跑。我的习惯是:手工排障用图形界面,批量复盘和例行巡检用tshark。
4.2 tshark统计长度的几组高频命令
有一组我几乎每天要用的命令,建议抄进自己的笔记:
# 列出每个包的编号和长度 tshark -r download.pcapng -T fields -e frame.number -e frame.len # 按长度聚合统计,得出每种长度的包数量 tshark -r download.pcapng -T fields -e frame.len | sort | uniq -c | sort -rn | head -20 # 统计长度大于1400字节的数据包个数 tshark -r download.pcapng -Y "frame.len > 1400" | wc -l # 查看最大的包长度 tshark -r download.pcapng -T fields -e frame.len | sort -n | tail -1在Windows上的cmd环境里没有wc命令,可以用find /c /v ""代替:tshark -r download.pcapng -Y "frame.len > 1400" | find /c /v ""。PowerShell里更简单,(tshark -r download.pcapng -Y "frame.len > 1400").Count直接拿数组长度。
这些命令组合起来,就能在几秒钟内产出一份长度统计报告。比如我把第二条命令的输出重定向到文本文件,再配合awk或者Excel,几分钟就能把几百个PCAP的统计结果汇总成一张总表,这活儿放图形界面里做至少折腾一上午。
4.3 自定义显示列,让长度值自己说话
除了统计面板,我还推荐把常用长度字段直接做成列表列,这样抓包文件一打开,长度相关的信息就摆在眼前,连过滤器都不用输。
操作很简单:在抓包列表的列标题区点右键,选Column Preferences,点左下角的加号新增一列,字段名填frame.len,标题写成"帧长默认就有,但我会额外加一列frame.cap_len,用来对照有没有截断。再加一列tcp.len,就能一眼区分纯ACK和数据包。
有了这三列,扫一眼列表就能快速识别:tcp.len为0的包多半是控制包,tcp.len接近1460或1448的是满载荷数据包。要统计某个方向的数据包长度,甚至可以直接在列表里数。
4.4 统计"某个IP发出的包长度分布"完整示例
假设我要分析192.168.1.100这个IP对外发送流量的大小特征,用一条命令就能出结果:
tshark -r capture.pcapng -Y "ip.src == 192.168.1.100" -T fields -e frame.len | sort | uniq -c | sort -rn输出大概长这样:
3420 54 1890 1514 320 66 180 256 80 1207看到这个结果,我会立刻意识到:3420个54字节包说明这个IP发出去大量纯ACK,1890个1514字节满帧说明它也在积极发送数据。如果这个IP是文件服务器,这个比例算健康;如果它是一个Web应用服务器而54字节包占大头,那就要查应用是不是频繁建立连接、频繁丢小请求,导致大量确认包往返。
5. 从长度统计反推网络问题
5.1 案例一:MTU/MSS异常排查
有一次用户反馈跨网段传文件经常卡住,我看了抓包统计,发现数据包最大长度只有576字节。这个数字很经典——它是很多老协议和隧道场景下的兜底MTU值。进一步看,所有超过576字节的IP包都被分片了。
这说明链路上某个环节的MTU比1500小,而中间设备可能在静默丢弃超过自身MTU的数据包,导致TCP探测不到真实MTU,只能靠分片或者降速来"苟着"。这种情况下,长度分布里大包占比会明显偏低,碎片化的小包占比升高。排查方向就变成:找出路径上MTU最小的设备,检查隧道封装是否有额外开销,确认两端网卡的MSS clamp配置。
5.2 案例二:小包风暴
开头说的那个客户案例,就是典型的小包风暴。我统计完发现,20秒抓包里一共有约20万个包,但其中超过1400字节的包只有5000个,剩下的几乎全是54到66字节的ACK和探测包。平均包长不到100字节,链路看起来"包很多、很忙",实际吞吐不到几Mbps。
这种场景通常不是带宽不够,而是应用层设计有问题:比如客户端不断发小查询请求,服务器处理完立刻回ACK但迟迟不发真正的业务数据;或者某个协议实现了很短的保活机制,每分钟发几十个探活包。应对方法分两层:网络层可以适当关注交换机CPU,应用层则要优化交互频率、合并请求、开启批量数据推送,把小包的数量降下来。
5.3 案例三:分片与异常大帧
长度统计还有一个容易被忽视的作用,就是快速发现分片和巨型帧问题。如果你看到大量IP包的长度不是1514或者正常数据包尺寸,而是出现一堆900、1480这类"半截"尺寸,并且分片信息里有很多"Fragmented IP protocol"标志,说明路径上的MTU和发送端不一致。
还有一种情况是我实际遇到过的:某台服务器网卡开了巨型帧(MTU 9000),但同网段交换机和另一端网卡没开。抓包里会出现超过1514字节的帧,比如2090字节或者更大,但这些帧过不了没开巨型帧的设备,导致丢包和重传。这种问题用Packet Lengths一眼就能识别:正常应该是1514封顶,结果冒出一堆3000、5000字节的包,那MTU配置肯定不统一。
5.4 案例四:协议开销计算
长度统计还能用来做链路容量规划。比如一段G.711语音,每20毫秒一个RTP包,帧长214字节,每秒50个包,单向速率就是214乘以50乘以8,约等于85.6kbps。再加上RTCP等控制流量,一路语音通话大概占90kbps上下。当你从抓包长度统计里看到大量214字节左右的规律包时,就可以反推线路正在承载多少路语音。
同样的算法可以套到任何业务上:用Packet Lengths算平均包长,再乘以每秒包数,就是这条流的实际带宽占用。我在写网络扩容方案时经常用这组数据,比直接拍脑袋估带宽靠谱得多。
6. 常见问题与避坑实录
6.1 为什么只显示520字节?
这是被问得最多的一个问题。现象是:抓包列表里很多包的Length列显示520,点开详情,数据内容到520字节就没了,Info列还带着"Packet size limited during capture"的提示。
原因几乎都是抓包时把snaplen设成了520。具体位置就是Capture Options里的"Limit each packet to"输入框。有人为了省磁盘空间把值调小,结果把完整的包截了肢;也有人是自己没注意,输入法手滑填了个520进去。
要确认一个已有的抓包文件是否被截断,用显示过滤器frame.cap_len < frame.len查一下,或者直接看Info列的提示。请注意,截断是捕获阶段就发生的,已经保存的文件救不回来,唯一的办法是重新抓包,把snaplen改回65535。
6.2 怎样抓出2090字节的完整数据?
如果确实需要看到2090字节甚至更长的完整包,分三步走:
第一,在Capture Options里把snaplen改成65535或者取消"Limit each packet to"的勾选,确保不会截断; 第二,确认整条链路上的网卡和交换机都允许这个帧长通过。普通的1500字节MTU根本不会有2090字节的帧,能出现这种帧说明某些设备已经开启巨型帧; 第三,抓包完成后,在包列表里点中目标包,右侧详情面板展开最底层的Data字段就能看到完整载荷。如果嫌麻烦,直接在包上右键选Follow TCP Stream,Wireshark会帮你把TCP流重组好,原始字节一个不落。
另外有个细节:个别网卡驱动在抓到巨型帧时可能会丢包或者截断到1514字节,这种属于硬件限制,需要确认网卡属性里是否启用了Jumbo Packet选项,并设置成匹配的MTU值。
6.3 长时间抓包的正确姿势
做长度统计有时候需要抓几小时甚至一整天的流量。这时候直接开着Wireshark抓,文件会膨胀到几十GB,统计界面也会卡成幻灯片。我建议用环形缓冲。
在Capture Options里勾选"Use multiple files",设置"Next file every"按时间或大小分片,比如每100MB切一个文件;再勾选"Use ring buffer with N files",比如填10,这样最多保留最近10个文件,老文件自动覆盖,磁盘永远不会爆。命令行版本对应是tshark -i eth0 -b filesize:102400 -b files:10 -w long_capture.pcapng,filesize单位是KB,102400就是100MB。
长时间抓包结束后的统计也要注意:不要直接对10个文件分别开Packet Lengths手动加总,正确做法是用tshark批量处理:
for f in long_capture_*.pcapng; do tshark -r "$f" -T fields -e frame.len done | sort | uniq -c | sort -rn | head -20这样能把所有分片文件合并算出一个总分布,避免手工汇总出错。
6.4 还有几个容易误判的细节
最后提醒几个实战中经常踩的坑。
第一个是校验和报错。抓包时如果看到大量"TCP checksum incorrect",先别急着判定网络损坏。很多网卡驱动开启了校验和卸载(Checksum Offload),发出的包在校验和字段填的是占位值,真正的校验和由网卡硬件在发送瞬间计算。这种情况在抓包里表现为发出方向包校验和"错误",实际网络上并没有问题。要准确检查,可以临时关掉网卡的TCP/IP校验和卸载功能再抓一次。
第二个是混杂模式。前面提过它默认开启,但有些抓包场景,比如Windows的无线网卡,即使开了混杂模式也抓不到其他设备的帧,这是驱动限制,不是统计逻辑出错。
第三个是抓包过滤器里不能直接写frame.len。抓包过滤器用的是BPF语法,只认识长度相关的原始字段,比如less 1000表示抓小于1000字节的包,greater 1400表示抓大于1400字节的包。这个概念和显示过滤器完全不同,混用最容易报错。
第四个是统计口径。同一个PCAP文件,用Packet Lengths统计的"包数"和用tshark的-Y "frame.len..."统计的结果必须一致,如果对不上,多半是你没注意truncated包的frame.len和frame.cap_len差异,或者混用了不同版本的过滤器语法。我一般在关键结论出来前,会先用tshark交叉验证一遍。
最后分享一个我自己的习惯:我电脑上长期放着一个叫pktstat.sh的脚本,里面就是第4节那几行tshark命令,每次拿到PCAP先跑一遍,输出保存成文本,再打开Wireshark看细节。这样的好处是统计结论有据可查、可复现,也方便后期做对比。数据包长度这个指标,看起来简单,但它就像测量一个人体温——不测不知道,测了之后很多隐藏问题都会自己浮出来。建议你下次抓完包,先别急着翻协议树,点开Packet Lengths,让数字先开口说话。