Wireshark发送方向数据包长度统计:从包长分布到性能排查实战
2026/9/19 9:53:20 网站建设 项目流程

Wireshark抓包这件事,很多人习惯盯着数据包内容看,一个Header一个字节地翻,却很少认真对待那个“数据包长度统计”。说实话,我之前也这样,直到有一次线上故障排查,被同事一句“你这抓包里怎么全是60字节的空包”点醒,才意识到包长分布这项统计在性能分析里有多好用。今天想把这块经验完整梳理一遍,重点讲怎么用它统计“发送方向”的数据包长度,包含计量原理、面板操作、命令行方案,还有几个我踩过的坑,尤其是那个常见的“只能显示520字节”的问题。

这个内容适合三类人看:第一类是刚入门Wireshark、还停留在用界面看包阶段的新手;第二类是网络运维或者后端开发,遇到“网络慢、响应卡、带宽被吃满”但不知道从哪下手排查的人;第三类是已经会基本过滤和跟踪流,但还没系统用过Statistics菜单的进阶选手。

1. 为什么关心“发送的数据包长度”:从一次故障说起

1.1 一次真实的线上问题

去年夏天我处理过一起应用响应变慢的事故。后端服务本身CPU、内存都正常,数据库也没有慢查询,但用户反馈接口时不时卡顿。我分别在客户端和服务端同时抓包,Wireshark打开后第一眼没看出什么协议异常,TCP没有大量重传,也没有RST断开,看起来“挺正常”。

后来我点了Statistics菜单下的Packet Lengths,问题立刻暴露了:整个会话里,80到159字节的小包占了将近70%,而正常业务的大数据包(1400字节以上)占比不到10%。配合Conversations列表一看,发现客户端每隔几十毫秒就在发一批小包,像是在疯狂建立短连接或者高频发心跳。顺藤摸瓜查过去,才发现是应用层一个定时任务在每次循环里都开了新的HTTP连接,而且没有复用,导致大量TCP握手包和ACK包把链路占满了。那一次排查,真正起决定性作用的就是包长统计这个视图。

从那以后,我养成了一个习惯:拿到一个pcap文件,先不看包内容,先看长度分布。就像一个医生拿到血常规化验单,先看红细胞白细胞计数,而不是直接看显微镜下的细胞形态。长度分布虽然不能告诉你包里面具体有什么,但它能快速告诉你这条链路上“正在发生什么类型的事”:是小包密集的控制流,还是大包密集的数据流,有没有异常巨型帧,有没有大量截断。

1.2 发送方向与接收方向,必须分开看

Wireshark的统计模块默认不做方向区分,它会把你捕获到的所有双向包混在一起统计。这在很多场景下会掩盖问题。设想一个场景:客户端在向服务器大量上传文件,服务器同时也在向客户端推送消息。如果你只看混合的包长分布,可能看到60字节小包和1400字节大包各占一半,只会觉得“有控制流也有数据流”,但根本分不清是哪一端在发小包、哪一端在发大包。

实际排查中,我们经常需要单独回答“这台主机对外发送的数据包长度分布如何”,比如判断某个设备是否在主动扫描网络、某个客户端是否在上传大文件、某个服务是否在向外打大量小包。这种情况下,就必须把“发送方向”单独筛出来。

方向怎么定义?通常有两种理解:第一种是IP层方向,即源IP是本机、目的IP是对端,用ip.src过滤;第二种是TCP/UDP端口方向,即源端口是本机服务端口,用tcp.srcport过滤。具体用哪种取决于你关心的是主机维度还是服务维度。大部分场景下,ip.src == 本机IP就能准确圈定“从本机发出去”的所有包,不论它是TCP、UDP还是ICMP。我在后面的实操里,默认都会带上ip.src过滤器,这样统计出来的才是“发送数据包”的长度分布,而不是混杂了双向流量的整体分布。

2. 数据包长度的“度量衡”:看懂frame.len和snaplen

2.1 Wireshark里的长度字段都表示什么

很多新手在Wireshark里点开一条数据包,看到好几处带有“Length”字样的字段,容易搞混。最常碰到的有三个:Frame块里的Length字段,IPv4头部里的Total Length字段,TCP头部里的Segment Length字段。

Frame块里的长度字段,完整说其实是两个:frame.len表示这个帧在链路上的实际长度(以字节为单位),也就是“在线上真实跑了多少字节”,包括以太网帧头、IP头、TCP头、应用载荷,还有底部的FCS校验可能包含的字节;frame.cap_len表示实际被Wireshark捕获并保存下来的长度。正常情况下两者一致,但如果抓包时设置过snaplen截断,cap_len就会小于len。这是后面讲“520字节”问题的关键。

IPv4的Total Length是IP层总长度,包含IP头本身载荷,但不包含以太网帧头和尾部。TCP的Segment Length通常表示这个TCP段承载的载荷字节数,不包含TCP头。三条长度之间是层层嵌套的关系:以太网帧长度约等于14(以太网头)+ IP Total Length;IP Total Length约等于20(IP头)+ UDP/TCP头 + 应用载荷。

为了直观理解,我在下面列几个常见包的典型长度范围:

包类型以太网帧总长(frame.len)说明
TCP SYN握手包约62字节14(以太头)+20(IP头)+20(TCP头)+8(TCP时间戳选项)等
TCP纯ACK包约60字节类似SYN,但选项可能更少,整体约60字节
空载UDP包(DNS查询)约60到100字节取决于DNS载荷大小
最大标准MTU数据包1518字节1500字节IP报文+14字节以太网头,不含FCS状态下常见显示1518
带VLAN标签的大包1522字节1500字节IP报文+4字节VLAN Tag+14字节以太网头

2.2 为什么抓包显示只有520字节(snaplen问题详解)

见识过真实场景的读者可能遇到过这种情况:Wireshark主界面里明明看到一条数据包,点进去后数据区后半部分全是灰色或者直接缺失,而顶部信息显示“520 bytes on wire, 520 bytes captured”。这里会出现两个长度不一致或者正好都显示520,是因为抓包工具在捕获时做了截断,只保留了每个包的前520字节。

Wireshark在Capture Options对话框里有一个设置叫“Limit each packet to X bytes”,这里的X默认是65535。如果这个值被改成了520,Wireshark就会对超过520字节的包做截断,只保存前520字节。为什么有人会改这个值?因为它能显著减小pcap文件的体积。在高流量链路上,如果不截断,一个抓包文件可能几分钟就上GB;把snaplen设成128或256,文件能小好几倍。代价就是应用层载荷后半段完全丢失,无法做数据重组。

但是我个人非常不建议在生产环境抓包时主动调小snaplen,除非你明确知道只需要看头部信息。原因很简单:一旦截断,后续再想做协议分析、文件还原、HTTP body提取,全部都会失败。截断数据的时间戳和包长信息还在,但载荷缺失会让你错过很多关键证据。

至于“怎么显示2090字节的数据”,那就简单了:把snaplen调回65535,重新抓包。如果用的是已保存的截断pcap,那没有办法补救,只能重新抓,因为丢失的载荷不会自己长回来。这个知识点虽然基础,但真的是很多人在Wireshark社区反复问的问题,我专门在这里写透。

2.3 如何正确设置抓包长度,避免截断

具体操作路径是:点击Wireshark主界面的齿轮图标或者直接按Ctrl+K打开“Capture Options”窗口,找到“Capture Filter”区域下方的“Limit each packet to”输入框,填入65535。如果是长期设置,可以到Edit->Preferences->Capture里修改默认值,这样每次新建抓包都会默认采用这个数值。

还有一个容易被忽略的点:在“Capture Options”里,除了snaplen,还要留意“Enable promiscuous mode”是否勾选。如果抓包需要关注本机对外发送的所有流量,混杂模式通常建议开启,否则网卡驱动会过滤掉目标MAC地址不是本机的包,导致统计结果缺了一大块。加上现代网卡普遍支持硬件卸载(如LRO/GRO),抓包时可能会看到超过1518字节的巨型帧,这是因为网卡已经把多个TCP段合并成一个大包交给Wireshark了,这是正常现象,不代表网络真的在发超长帧。这个坑等会儿单独展开讲。

3. 实操:Packet Lengths统计面板的完整用法

3.1 打开Packet Lengths并设置分桶

现在假设已经有一个采集好的pcap文件,并且确认snaplen是65535,没有截断。点击菜单栏的Statistics->Packet Lengths,会弹出一个新的统计窗口。界面上方有两个输入框:一个是“Interval”,用来控制分桶大小;另一个是“Ignore packets shorter than”,用来过滤掉过小的包。默认的Interval是40,意思是从0开始,每40字节一个区间,直到1518以上。

这里的分桶大小很关键,设置不同看到的结论会完全不同。如果用默认的40字节一档,那么0到39、40到79、80到119这样逐段划分,80到159这一档会包含很多TCP控制包,因为60字节的ACK、62字节的SYN都在这个区间。如果你关心的是大数据包的分布,可以把Interval调大,比如200,甚至直接选择按2的幂次分桶;如果你关心的是小包和正常数据包的边界,用40就很合理。

窗口下半部分有两块内容:左边是表格,列出每个长度区间内的包数量、占比、累计包数、累计字节数;右边是图形,用柱状图直观展示分布。建议看表格时重点看四个指标:包数占比、字节数占比、累计包数、累计字节数。占比最直观,但字节数占比能告诉你“谁在真正占带宽”。举例来说,一个小包区间可能数量占比达到80%,但字节数占比只有5%,说明链路上虽然包很多,但数据量很轻。

3.2 只统计发送方向的数据包

打开Packet Lengths窗口时,它默认会统计当前Wireshark主界面里显示的所有包。如果主界面有显示过滤器生效,那么统计窗口会跟随过滤条件,只统计过滤后的包。所以想统计“发送方向”的数据包长度,最直接的办法是在主界面的显示过滤器栏里输入类似ip.src == 192.168.1.100的过滤条件,然后再打开Packet Lengths。

这里有一个细节需要注意:显示过滤器是事后过滤,它只会影响统计范围,不会影响pcap文件本身。所以即使你过滤了ip.src==客户端IP,统计结果也只是“从该IP发出的包”,完全符合“发送数据包长度”的需求。但如果你的pcap文件非常大,几GB级别,每次点统计都卡半天,那更好的做法是在抓包时就加上捕获过滤器。捕获过滤器的写法是src host 192.168.1.100,它在网卡层面就丢弃不相关的包,既能减小文件体积,也能让后续统计更快。

我平时最常用的组合是双保险:抓包时用捕获过滤器src host 客户端IP or dst host 客户端IP,把与这个IP相关的双向流量完整抓下来;分析时再用显示过滤器ip.src == 客户端IP单独看发送方向。这样既能保底不遗漏信息,又能灵活切换方向。

3.3 读出表格里的信息:数量、占比、累计

拿一次典型的HTTP大文件下载抓包来举例子。客户端向服务器下载一个200MB的文件,理论上应该看到大量1518字节左右的以太网帧(因为TCP MSS协商后,双方都以最大段尺寸发送)。如果看Packet Lengths,你会发现“1440到1518”这个区间的包数量占比可能超过60%,字节数占比甚至超过90%。这说明数据传输非常健康、效率很高。

反过来,如果看到80到159字节区间的包数量占比很高,而1440到1518区间占比很低,那就说明链路上“控制包密集、数据包稀少”。这种模式在几种场景下都常见:一是DDoS攻击中的TCP SYN Flood或ACK Flood,攻击者发大量60字节左右的包;二是应用层存在高频心跳或轮询,比如某些聊天软件每两秒发一个几十字节的保活包;三是TCP没有开启延迟确认,导致每收到一个数据段就回一个40到60字节的ACK包。到底属于哪一种,可以在包长统计基础上叠加Statistics->Conversations,看看这些大流量小包来自哪个IP、哪个端口,再进一步跟进去看包内容。

另外一个很实用的场景是判断MTU协商是否正常。如果客户端MTU设置成1500,但中间链路MTU更小(比如PPPoE链路的1492),那大包会被分片。在包长统计里,如果看到大量1594、1894之类的区间(比1518更大),说明出现了分片或者网卡开启了巨型帧。这个信息靠肉眼看列表很难发现,但长度分布图表上一目了然。

4. 进阶:用tshark和导出做更细的统计

4.1 tshark一行命令完成统计

Wireshark的图形化界面方便,但有些场景必须在命令行下工作,比如在远程服务器上抓包,或者要批量处理一堆pcap文件。Wireshark自带的tshark命令行工具可以直接输出Packet Lengths统计,效果和图形界面完全一致。

最基本的一条命令是:

tshark -r capture.pcapng -q -z pktlen

-r指定读取的抓包文件,-q表示安静模式、不逐个打印每包详情,-z pktlen表示输出包长统计。加上过滤条件也很方便,比如只看某个源IP发送的包:

tshark -r capture.pcapng -q -z pktlen,"ip.src==192.168.1.100"

注意过滤条件是用引号括起来、整体作为-z的参数。输出的表格和图形界面里的Packet Lengths窗口内容一致,包含区间、数量、占比、累计等列。批量处理多文件时,我一般写个Shell循环,对每个文件跑一遍这条命令,再把结果重定向到文本文件里,一次性对比多个时间段的包长分布,非常适合做趋势分析。

4.2 按IP/端口拆分发包长度的分布

-z pktlen只能给出整体分布,如果想知道“每个IP各自发的包长分布”,就需要用按会话统计的方式。tshark里和它配合使用的是-z conv,ip,它能按IP地址对列出双向会话的包数和字节数;但你要的是每个IP单独发送方向的包长分布,直接看conv还不够细。

更灵活的做法是用tshark导出字段,再交给其他工具做聚合。先导出每个包的帧长度、源IP、目的IP、源端口、目的端口:

tshark -r capture.pcapng -T fields \ -e frame.number -e frame.len -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport \ -E header=y -E separator=, > packets_len.csv

导出后就是一个CSV文件,每一行是一个包的基础信息。接下来在Excel里做数据透视表,行放ip.src,列放frame.len的分桶区间,值放计数,就能一秒看出“哪个源IP在大量发送小包”。这个方法比直接在Wireshark里点统计更灵活,也更容易做跨文件对比。

4.3 导出CSV后用Excel做透视分析

具体在Excel里怎么操作,我说一下我的习惯。第一步,打开CSV后选中所有列,插入一个数据透视表。第二步,把ip.src拖到“行”区域,把frame.len拖到“列”区域,把frame.len(或者任意字段)再拖到“值”区域,改成“计数”。这时候透视表会按源IP和帧长度列出所有组合的包数量。第三步,右键frame.len列标签,选“组合”,设置起始于0、终止于1600、步长150,就能得到一个类似Packet Lengths的分桶计数结果。第四步,对“计数”列排序,看哪些IP的包数最多,再针对可疑IP回到Wireshark里单独过滤。

这套流程看着多,但熟练后处理一个1GB的pcap文件也就是几分钟的事。尤其适合那种“网络感觉慢但说不清哪里慢”的场景:先用透视表找到高包量IP、高包量长度区间,再缩小范围看具体会话,定位效率比漫无目的地翻包高得多。

5. 常见问题与排查技巧实录

5.1 为什么统计结果全是80~159字节的小包

这个问题我遇到不下十次。第一次是在一个无线网络优化项目里,客户说带宽被占用严重,可实际流量不高。抓包后的Packet Lengths一片红,全是80到159字节的区间。后来定位到是设备上的某种网络管理协议在每秒钟广播大量小型报文,把无线信道占掉了大半。

遇到统计全是小包,第一步先看是不是TCP控制包。在Wireshark里加一个显示过滤器tcp.analysis.flags,如果统计后命中比例很高,说明小包多是重传、重复ACK、零窗口探测这类TCP异常报文,根因在网络链路质量或者收发端缓冲区设置。第二步看流量方向,如果小包集中来自某一个IP,且该IP不是业务服务器,就要警惕扫描行为。第三步看协议分布,用Statistics->Protocol Hierarchy,如果DNS查询或者NTP请求占了很大比例,说明是有设备在频繁做域名解析或时间同步。

有一种最容易被忽略的情况:如果设置了snaplen截断,比如只抓前128字节,那么所有被抓下来的包在长度列里都会显示128以内,无论原始包多大。这时候Packet Lengths看起来也会是“小包一统天下”,但这是假象,是截断造成的。怎么区分?看Frame块的frame.lenframe.cap_len是否相等,如果不相等,就是截断了,先解决抓包设置再说。

5.2 TCP分片与长度统计的关系

标准以太网MTU是1500字节,对应的完整帧长度通常是1518字节。但如果你在Packet Lengths里看到超过1518的区间,比如1600、1800甚至更多,就需要分情况讨论。

第一种情况是网卡开启了巨型帧,MTU被调到9000,那么正常数据包长度就可能达到9000以上。这种情况在数据中心内部存储网络、NFS、iSCSI环境里很常见。写博文时你只需要知道:长度统计里出现超长帧不一定是坏事,先确认是不是巨型帧环境。

第二种情况是802.1Q VLAN标签。在标准以太网帧里插入4字节的VLAN Tag后,帧长度最大可到1522字节。如果交换机配置了QinQ(802.1ad),还可能出现1526字节的帧。

第三种情况是IP分片。当一个大于MTU的IP报文被路由器分片时,每个分片本身不会超过MTU,所以在标准网络里,单条帧长度仍然不会超过1518。但如果你抓包点位于隧道两端(比如VXLAN、GRE隧道),外层封装会让帧长度显著超过1518。遇到这种情况,单纯看包长无法判断是分片还是封装,需要配合IP头的Identification字段、More fragments标志位以及协议类型综合判断。检查分片的最快方式是在主界面输入ip.flags.mf == 1或者ip.fragments,看看有没有分片报文。

5.3 “520字节”与“2090字节”:一次显示异常排查

聊到5.3这个环节,我想把标题里那个高频问题完整复盘一遍。有一次论坛上有人发帖,说Wireshark里面看到一条数据包长度显示只有520字节,但根据应用层协议,这个包实际应该有2090字节,问为什么Wireshark显示不全。下面回帖众说纷纭,有说网卡问题、有说驱动问题、还有人怀疑Wireshark的BUG。

实际情况很简单:抓包时,抓包工具的snaplen被设置成了520。当Wireshark打开这个包时,由于数据本身只捕获了520字节,它只能显示这520字节的内容,后面的载荷区域就是灰的。那2090字节是从哪里来的?可能是包列表里显示的长度,也可能是协议头里声明了更长载荷,但实际捕获数据里根本没有。

这个问题要分两层解决。如果原始采集还没有停止,赶紧调整抓包配置:打开Capture Options,把“Limit each packet to”后面的数字改大,比如改成65535,然后重新抓包。如果pcap已经保存并且停止抓包了,那么抱歉,截断的数据无法恢复,唯一办法是回去重新抓。网上有一些工具声称可以“修复”截断的pcap,但严格来说,它只能修复文件结构损坏问题,无法凭空补出没抓到的载荷字节。

很多人不知道的是,Wireshark在截断情况下仍然会保留“原始在线长度”和“捕获长度”两个值。打开帧数据,展开Frame块,能看到“Length: 2090”和“Captured Length: 520”两个字段,前者是线上真实长度,后者是实际捕获长度。当这两个数值不一样时,就说明抓包阶段发生了截断。所以如果你要复现“看到2090字节完整数据”的效果,必须确保frame.lenframe.cap_len相等。

这个“520”和“2090”的问题,本质上是抓包阶段数据完整性的问题。为了避免以后再遇到,我的建议是:只要条件允许,snaplen一律设成65535,不要为了省存储空间而牺牲载荷完整性。如果实在担心文件太大,可以搭配环形缓冲或抓包自动停止条件,而不是靠截断来减小文件。


写到这里,我还是想多说一句个人体会。我后来每次拿到一个pcap文件,基本会先看两个统计,一个是Packet Lengths,一个是Conversations。前者告诉我链路上是什么类型的流量在跑,后者告诉我这些流量到底是哪个IP、哪条连接产生的。两个一交叉,大部分“网络有问题但不知道哪里的问题”的排查,都能在两分钟内划出一个大概的范围。尤其是发送方向的包长统计,配合ip.src过滤后,在判断“是不是某台设备在向外打小包、是不是某个客户端在上传大文件、有没有异常的长包扫描”这些场景里,真的比单纯翻包要高效得多。最后再分享一个小技巧:如果你怀疑抓包文件有截断,直接在过滤栏输入frame.len != frame.cap_len,如果有任何包命中,说明这个文件中存在截断包,需要回头检查抓包时的snaplen设置。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询