资讯动态

Wireshark抓包实战:解剖TCP三次握手与四次挥手的真实流量

发布时间:2026/10/20 22:38:33 来源:尧图企业网站定制
1. 为什么抓包看三次握手比背定义管用十倍我带过不少刚学网络的新人发现一个特别普遍的现象他们能把TCP三次握手的SYN、SYN-ACK、ACK背得滚瓜烂熟也能默写出四次挥手的FIN、ACK、FIN、ACK顺序但一遇到线上服务连接超时、接口偶发503、或者Wireshark里一堆RST包不知道从哪来的立刻就懵了。不是概念没懂是根本没见过真实流量长什么样。这就像学开车只背《道路交通安全法》条文——你知道“红灯停绿灯行”但没在早高峰的十字路口踩过刹车、没被加塞过、没经历过雨天ABS介入的震动你永远算不上会开车。TCP协议也一样它不是纸面上的流程图而是每毫秒都在网卡和内核里真实发生的字节流搏斗。抓包实验就是把TCP从教科书里拽出来按在地上让你看清它的指纹、心跳和伤疤。你亲眼看到客户端SYN包的TTL是64还是128能发现服务端回的SYN-ACK里Window Size突然缩到0能确认那个“连接已关闭”的FIN包到底是谁先发的、对方有没有真正收到ACK……这些细节决定了你是能快速定位是防火墙策略问题还是应用层主动abort还是中间设备悄悄reset了连接。更关键的是真实环境里根本不存在“标准三次握手”。你抓到的包里可能夹着TCP Timestamp、SACK Permitted、MSS协商甚至TLS握手直接叠在第三次ACK之后四次挥手可能被优化成三次FINACK合并也可能因为TIME_WAIT状态堆积导致端口耗尽。这些都不是理论漏洞而是每天在生产环境里真实咬人的刺。所以别再对着RFC文档空想“理想状态”了。接下来我要带你做的不是复现教科书流程而是用Wireshark亲手解剖一次真实的TCP连接诞生与死亡全过程——从第一个SYN包的IP头校验和到最后一个TIME_WAIT超时的内核日志所有步骤都附带我在某跨平台系统压测中踩过的坑和验证过的参数逻辑。2. 抓包前必须掐灭的五个“理所当然”幻觉很多人第一次抓包就失败不是工具不会用而是脑子里预设了太多“应该如此”的幻觉。这些幻觉像一层毛玻璃让你明明看到了包却读不懂它在说什么。我列出了最常绊倒新手的五个认知陷阱每个都配了真实抓包截图里的反例2.1 幻觉一“SYN包一定来自客户端SYN-ACK一定来自服务端”真相TCP连接没有绝对的“客户端/服务端”身份只有发起方和响应方。当你用curl http://localhost:8080访问本机服务时SYN包源IP和目的IP都是127.0.0.1Wireshark里显示为“127.0.0.1 → 127.0.0.1”此时你根本分不清谁是client谁是server——只能靠端口号判断随机高位端口如52341是发起方固定端口如8080是监听方。提示在Wireshark过滤栏输入tcp.flags.syn 1 and ip.src 127.0.0.1你会看到本机自连时SYN包的源端口全是动态分配的这才是真实世界的样子。2.2 幻觉二“三次握手必须严格按时间顺序不能有重传”真相网络是不可靠的。我曾在某高校实验室的千兆局域网里抓到过SYN包重传间隔达1.1秒标准初始RTO是1秒。原因当时交换机上启用了QoS策略对SYN包做了低优先级队列。Wireshark里你会看到两个SYN包时间戳相差1.1秒第二个SYN的Seq Number和第一个完全一致因为重传不改变序列号。验证方法在Wireshark里右键第一个SYN包 → “Follow” → “TCP Stream”对比两个SYN包的Sequence number字段。如果相同就是重传如果不同那就是新连接。2.3 幻觉三“SYN-ACK包里的Window Size就是服务端接收缓冲区大小”真相Window Size字段是通告窗口Advertised Window它告诉对方“我现在还能收多少字节”但这个值受操作系统内核参数、当前内存压力、甚至TCP选项影响。比如Linux默认net.ipv4.tcp_rmem是“4096 131072 6291456”但SYN-ACK里通告的Window Size可能是8192——因为内核在握手阶段保守地只宣告初始窗口。实测对比我在某图像处理Demo中将服务端tcp_rmem最小值调高到65536再抓包SYN-ACK的Window Size果然从8192涨到了65536。但注意这不代表服务端真能立刻收65536字节它只是“说”自己能收这么多。2.4 幻觉四“四次挥手时主动关闭方一定会进入TIME_WAIT状态”真相TIME_WAIT是主动发送最后一个ACK的一方进入的状态不是“主动关闭方”。举个反直觉的例子客户端发FIN→服务端回ACK此时服务端还没发FIN接着服务端发FIN→客户端回ACK。这时客户端是主动关闭方但它发完最后一个ACK后进入TIME_WAIT但如果服务端在收到客户端FIN后立刻也发FIN即同时关闭那么服务端发的FIN和ACK可能合并此时服务端反而先进入TIME_WAIT。注意Linux内核有个net.ipv4.tcp_fin_timeout参数默认60秒但TIME_WAIT实际持续时间是2MSLMaximum Segment Lifetime通常为2×60120秒。别被参数名骗了。2.5 幻觉五“抓包看到RST包一定是程序崩溃或异常终止”真相RSTReset包是TCP的“紧急制动”它出现的原因极其多样。我整理了一个高频场景对照表全是某跨平台系统上线后真实抓包分析得出的结论RST触发场景Wireshark关键特征如何验证客户端向未监听端口发SYN源IP是客户端目的IP是服务端目的端口无服务netstat -tuln | grep :端口号确认端口是否监听服务端收到重复SYN已建立连接同一五元组源IP源端口目的IP目的端口协议出现第二个SYN过滤tcp.flags.syn 1 and tcp.stream eq X看是否有重复SYN中间设备防火墙/NAT策略拦截RST包TTL值异常如非64/128且源IP是中间设备IP对比前后包TTL查网络拓扑应用层主动close()后又发数据RST包前有一个FIN包且FIN后还有应用数据包Follow TCP Stream看FIN后是否还有Payload这些幻觉不破除你抓一万次包看到的也只是乱码。真正的网络排错是从质疑“理所当然”开始的。3. Wireshark实战从零构建可复现的三次握手观测环境光讲原理没用现在我们动手搭建一个100%可控、结果可预测、问题可复现的抓包环境。这不是随便ping一下就完事而是精确到每个包的序列号、时间戳、TCP选项的完整闭环实验。整个过程我用某图像处理Demo做载体所有配置和命令都经过实测验证。3.1 环境准备三台虚拟机的精简拓扑我们不用复杂网络只用三台轻量级虚拟机VM1、VM2、VM3全部桥接同一物理网段确保流量不经过任何路由器或NAT设备排除干扰VM1ClientUbuntu 22.04IP 192.168.1.10安装curl和ncatVM2ServerUbuntu 22.04IP 192.168.1.20运行Python简易HTTP服务VM3SnifferUbuntu 22.04IP 192.168.1.30仅安装Wireshark不参与通信关键点VM3作为纯抓包机必须禁用所有网络服务sudo systemctl stop apache2 nginx并关闭防火墙sudo ufw disable避免自身产生干扰流量。这是很多教程忽略的致命细节——如果你在抓包机上开着SSHWireshark里会混入大量SSH握手包淹没目标TCP流。3.2 服务端启动一个故意留“破绽”的Python服务在VM2上运行以下Python脚本server.py它故意在三次握手完成后、应用层响应前加入2秒延迟让我们有足够时间在Wireshark里精准定位握手完成点import socket import time # 创建TCP socket s socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((0.0.0.0, 8080)) s.listen(1) print(Server listening on port 8080...) while True: conn, addr s.accept() print(fConnection from {addr}) # 关键三次握手在此刻已完成但应用层尚未读取数据 # 我们在这里暂停2秒让Wireshark清晰捕获握手完成时刻 time.sleep(2) # 读取请求此时才真正进入应用层 data conn.recv(1024) if data: response bHTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World! conn.send(response) conn.close()启动命令python3 server.py 验证在VM1执行curl -v http://192.168.1.20:8080应看到2秒后返回Hello World!。3.3 抓包机配置Wireshark的三个必调参数在VM3Wireshark上不要直接点“Start Capture”。先做三件事设置捕获过滤器Capture Filter在主界面左上角“Capture Options”里输入host 192.168.1.10 and host 192.168.1.20 and port 8080这确保只捕获VM1和VM2之间的8080端口流量过滤掉所有ARP、DNS等杂包。实测中没加这个过滤器1秒内Wireshark会涌入200无关包根本找不到目标流。启用TCP时间戳解析菜单栏Edit → Preferences → Protocols → TCP勾选Calculate conversation timestamps和Relative sequence numbers。前者让Wireshark自动计算RTT往返时延后者将绝对序列号转为相对值从0开始极大降低阅读难度。设置显示过滤器Display Filter预置在Wireshark主窗口下方过滤栏提前保存三个常用过滤tcp.flags.syn 1只看SYN包tcp.stream eq 0只看第一个TCP流即本次实验的连接tcp.analysis.retransmission只看重传包提示Wireshark的tcp.stream eq X编号不是固定不变的。每次抓包新连接会按捕获顺序编号为0、1、2……所以务必在发起curl前开始抓包并在curl返回后立即停止确保目标流是stream 0。3.4 执行抓包一次精准到毫秒的操作链按顺序执行以下四步缺一不可在VM3上启动Wireshark确认捕获接口是eth0对应桥接网卡点击“Start”。在VM1上执行time curl -s -o /dev/null http://192.168.1.20:8080time命令会输出真实耗时记下这个值比如2.032s。在VM3上立即点击“Stop”停止抓包。在Wireshark里应用过滤器tcp.stream eq 0聚焦到本次连接。此时你应该看到7个核心包不是教科书说的3个按时间顺序排列包序方向标志位关键字段说明1VM1→VM2SYNSeq0, Win64240客户端发起初始序列号为0相对值2VM2→VM1SYN, ACKSeq0, Ack1, Win65535服务端响应确认收到SYN窗口655353VM1→VM2ACKSeq1, Ack1, Win64240客户端确认三次握手完成4VM1→VM2PSH, ACKSeq1, Ack1, Len74HTTP请求数据紧随ACK发出5VM2→VM1ACKSeq1, Ack75, Win65461服务端确认收到请求6VM2→VM1PSH, ACKSeq1, Ack75, Len30HTTP响应数据7VM1→VM2ACKSeq75, Ack31, Win64240客户端确认收到响应看到第3个包ACK时三次握手就结束了。从包1到包3的时间差就是你的握手时延Handshake Latency。在我的实测环境中这个值是0.182ms——远小于curl总耗时2.032s证明后续2秒延迟确实来自服务端time.sleep(2)而非网络问题。3.5 验证实验用tcpreplay制造“网络拥塞”再抓包为了验证前面说的“SYN重传”我们用tcpreplay工具人为制造丢包。在VM3上安装sudo apt update sudo apt install tcpreplay然后导出刚才抓到的stream 0的pcap文件File → Export Specified Packets命名为handshake.pcap。再用以下命令重放但强制丢弃50%的SYN包sudo tcpreplay --intf1eth0 --topspeed --loop10 --enable-file-cache --mbps100 --stats1 \ --filtertcp.flags.syn1 --skipbroadcast \ handshake.pcap此时在VM2上用sudo tcpdump -i eth0 tcp port 8080 -w server.pcap抓包你会看到大量SYN包但SYN-ACK极少——因为SYN被丢弃服务端根本没收到。这就是典型的“握手失败”场景Wireshark里会显示tcp.analysis.retransmission标记。这个实验的价值在于它把抽象的“网络不稳定”变成了可视化的丢包率、重传次数、RTO增长曲线。你不再需要猜而是直接看数据。4. 四次挥手深度解剖为什么TIME_WAIT不是bug而是救命稻草很多人把TIME_WAIT视为洪水猛兽认为它占端口、拖慢连接复用甚至盲目调大net.ipv4.tcp_fin_timeout。但在我维护某跨平台系统的三年里所有因TIME_WAIT引发的故障根源都不是TIME_WAIT本身而是对它的误解。现在我们用抓包数据一层层剥开它的真相。4.1 挥手过程还原从“教科书四次”到“现实三次”的演变继续用前面的VM1-VM2环境在VM2的server.py里把conn.close()改成conn.shutdown(socket.SHUT_RDWR)这样服务端会主动发FIN。然后重新抓包你会看到经典的四次挥手包序方向标志位Seq/Ack说明8VM2→VM1FIN, ACKSeq31, Ack75服务端发起关闭序列号31上一个PSH包的Len30所以FIN的Seq301319VM1→VM2ACKSeq75, Ack32客户端确认FINAck32FIN占用1字节序列号10VM1→VM2FIN, ACKSeq75, Ack32客户端也关闭发FIN11VM2→VM1ACKSeq32, Ack76服务端确认客户端FIN但注意包8和包9之间的时间差。在我的实测中这个间隔是0.000002秒2微秒——几乎同时。Wireshark会把它标记为“TCP Previous segment lost”吗不会。因为TCP允许延迟ACKDelayed ACK内核会等最多200ms看是否有数据要一起发。但这里没有数据所以ACK立刻发出。更常见的情况是“三次挥手”当一方发FIN后另一方恰好也有数据要发就会把ACK和FIN合并。比如VM1在收到VM2的FIN后不单独发ACK而是把ACK和自己的FIN打包在一个包里发出。此时你只看到三个包FIN、FINACK、ACK。这不是错误而是TCP的优化机制。4.2 TIME_WAIT的2MSL之谜为什么必须是120秒MSLMaximum Segment Lifetime是IP协议规定的报文在网络中存活的最长时间RFC 793定义为2分钟。TIME_WAIT持续2MSL即240秒是为了两个目的确保最后的ACK被对方收到如果客户端发的最后一个ACK丢了服务端会重传FIN。客户端在TIME_WAIT状态就能收到这个重传的FIN并再次发ACK。如果没有TIME_WAIT客户端直接关闭服务端FIN重传就没人理连接无法彻底关闭。防止旧连接的报文干扰新连接假设客户端用端口52341连接服务端。连接关闭后客户端立刻用同一端口52341发起新连接。如果网络中有上一个连接的“迷途”报文比如延迟了119秒才到达它会被新连接误收造成数据混乱。2MSL确保所有旧报文都已消亡。实测验证在VM2上执行ss -tan state time-wait | wc -l可查看当前TIME_WAIT连接数。在我的压测中单机并发1000连接TIME_WAIT峰值约200个远低于Linux默认net.ipv4.ip_local_port_range的32768-60999共28232个端口根本不会耗尽。4.3 真正的杀手CLOSE_WAIT而非TIME_WAIT运维同学最常喊“端口不够用”但查netstat -an \| grep CLOSE_WAIT往往发现几百个CLOSE_WAIT连接。这才是真正的资源泄漏CLOSE_WAIT状态表示对方已发FIN本方收到了但应用层代码没调用close()。它卡在内核和应用层之间既不释放端口也不发送FIN像僵尸一样挂着。如何抓到它在VM2上修改server.py注释掉conn.close()然后发起10次curl。再执行ss -tan state close-wait | awk {print $5} | sort | uniq -c | sort -nr你会看到大量192.168.1.10:xxxx证明客户端已断开但服务端没关连接。解决方案只有一个检查应用代码确保finally块里有conn.close()。在Go里是defer conn.Close()在Java里是try-with-resources原理都一样——让资源释放成为语法强制。4.4 生产环境TIME_WAIT调优什么时候该动内核参数盲目调小net.ipv4.tcp_fin_timeout是危险的。正确的调优路径是先确认是否真是TIME_WAIT瓶颈ss -s查看TCP: time wait数量再对比net.ipv4.ip_local_port_range的端口总数。如果TIME_WAIT 端口总数的10%无需调优。开启TIME_WAIT重用谨慎echo 1 /proc/sys/net/ipv4/tcp_tw_reuse这允许内核将TIME_WAIT状态的端口用于新连接但仅当新连接的时间戳严格大于旧连接时才允许。它依赖net.ipv4.tcp_timestamps1默认开启。我的建议仅在客户端如负载均衡器开启服务端永不开启。终极方案连接池与其调内核不如让应用层复用连接。在VM1上用curl --http1.1 --keepalive-time 60你会发现10次请求只用1个TCP连接TIME_WAIT归零。记住TIME_WAIT是TCP可靠性的基石。你消灭它得到的不是性能而是难以复现的偶发错误。5. 从抓包到排错一个真实线上故障的完整排查链路理论和实验都做了现在看它怎么解决真实问题。去年某图像处理Demo上线后用户投诉“上传图片偶尔失败提示‘连接被重置’”监控显示成功率99.2%但P99延迟飙升到8秒。以下是我在现场用抓包技术一步步定位的过程所有步骤均可复现。5.1 故障现象初筛用curl和tcpdump快速定界第一步不打开Wireshark用最轻量的工具缩小范围在用户机器模拟客户端执行curl -v -X POST --data-binary test.jpg http://api.example.com/upload输出显示* Failed to connect to api.example.com port 443: Connection reset by peer在服务端VM2执行sudo tcpdump -i eth0 host 用户IP and port 443 -w debug.pcap抓包10秒发现根本没有收到用户的SYN包。结论问题不在服务端而在用户到服务端之间的路径。可能是防火墙、LB、或中间代理。5.2 中间设备抓包在负载均衡器上镜像流量我们的架构是用户 → 公网SLB → 内网Nginx → 应用服务。既然服务端没收到SYN问题一定在SLB或Nginx。登录SLB管理后台开启“镜像流量到指定服务器”功能目标设为VM3抓包机。在VM3上执行sudo tcpdump -i eth0 port 443 -w slb.pcap抓包后用Wireshark打开过滤ip.addr 用户IP and tcp.flags.syn 1果然看到用户的SYN包但没有对应的SYN-ACK。说明SLB收到了SYN但没转发给后端或后端没响应。5.3 关键突破发现SYN包的TCP选项异常放大SYN包看TCP选项字段Options部分正常SYN包MSS1460, SACK_PERMITTED, TIMESTAMP, NOP, NOP故障SYN包MSS1460,WSCALE7, SACK_PERMITTED, TIMESTAMP, NOP, NOPWSCALEWindow Scale选项正常但值为7意味着窗口扩大因子是2^7128。而我们的SLB配置了最大窗口为6553565535×1288,388,480字节远超SLB处理能力导致其静默丢弃SYN包。验证在用户机器上执行curl --limit-rate 100K -v ...限制上传速度问题消失。因为低速上传时客户端TCP栈自动降低WSCALE值。根因用户使用了某国产手机厂商的定制ROM其TCP栈在高带宽网络下激进启用WSCALE7而老旧SLB固件不支持大窗口。5.4 终极修复两端协同的低成本方案不升级SLB成本高、周期长我们做了两件事服务端内核调优VM2# 降低初始窗口减少WSCALE需求 echo net.ipv4.tcp_rmem 4096 131072 2097152 | sudo tee -a /etc/sysctl.conf sudo sysctl -p客户端SDK适配App端在Android SDK里创建Socket时显式设置Socket socket new Socket(); socket.setReceiveBufferSize(65535); // 限制接收缓冲区 socket.connect(new InetSocketAddress(host, port), 5000);这样TCP栈协商时WSCALE会自动降为0即不启用窗口缩放。效果故障率从0.8%降至0.002%且无需改动任何中间设备。这个案例说明抓包不是终点而是起点。它给你的是证据链而解决问题需要你理解证据背后的协议逻辑、设备能力和业务约束。每一次成功的排错都是对TCP协议一次更深的致敬。6. 超越抓包用eBPF实时观测内核TCP状态Wireshark再强大也只是在网络层“看”包。而真正的瓶颈往往藏在内核TCP状态机内部。比如为什么SYN包发出去了SYN-ACK却迟迟不来是路由问题防火墙拦截还是本地端口耗尽这时候你需要穿透Wireshark直接读取内核的TCP控制块TCP Control Block。eBPFextended Berkeley Packet Filter就是这把手术刀。它允许你在不修改内核、不重启服务的前提下实时提取内核函数的执行信息。下面是在某跨平台系统中我用eBPF追踪TCP连接建立失败的实战。6.1 eBPF环境搭建5分钟极速部署在VM2服务端上用libbpf-bootstrap模板快速生成项目# 安装依赖 sudo apt install -y git build-essential libelf-dev libssl-dev zlib1g-dev # 克隆模板 git clone https://github.com/libbpf/libbpf-bootstrap cd libbpf-bootstrap/examples/c # 编译TCP观测程序 make tcpconnecttcpconnect是一个经典eBPF程序它挂载在tcp_connect内核函数上每当应用调用connect()时就打印源/目的IP、端口、返回值。6.2 追踪连接失败从“连接超时”到“端口耗尽”的精准诊断在VM1上用stress-ng制造端口压力# 占用1000个临时端口 stress-ng --tcp 1000 --timeout 60s同时在VM2上运行sudo ./tcpconnect输出类似PID COMM IP SADDR DADDR DPORT RET 12345 curl 4 192.168.1.10 192.168.1.20 8080 -99 12346 wget 4 192.168.1.10 192.168.1.20 8080 -99RET-99对应-EADDRNOTAVAIL即“地址不可用”。查Linux errno定义这是bind()失败原因是net.ipv4.ip_local_port_range已耗尽。而如果RET-111ECONNREFUSED则说明服务端没监听RET-110ETIMEDOUT则是网络层超时。eBPF把模糊的“连接失败”翻译成了精确的errno省去90%的猜测时间。6.3 深度追踪观测TIME_WAIT连接的生命周期tcpconnect只能看新建连接。要观察TIME_WAIT需用tcplife同属bpftrace工具集sudo tcplife -D # -D显示详细信息输出中你会看到PID COMM LADDR LPORT RADDR RPORT TX_KB RX_KB MS 12345 python3 192.168.1.20 8080 192.168.1.10 52341 0 0 120123最后一列MS是连接存活毫秒数。当它接近120000120秒时连接即将退出TIME_WAIT。你可以用watch -n 1 sudo tcplife -D \| grep 52341实时监控单个连接。6.4 eBPF与Wireshark的黄金组合eBPF告诉你“发生了什么”如connect()返回-99Wireshark告诉你“网络层看到什么”如SYN包是否发出。两者结合才是完整的真相。例如当eBPF显示RET-99而Wireshark在客户端抓包却看不到任何SYN包——这证明问题在本地端口分配阶段根本没走到发包如果Wireshark看到SYN包但没SYN-ACK则问题在服务端或中间网络。这种组合拳让我在某次CDN故障中3分钟内定位到是边缘节点的net.ipv4.ip_local_port_range被错误配置为1024-65535只留1023个端口而非标准的32768-65535导致高并发时连接雪崩。提示eBPF程序必须用sudo运行且内核版本需≥5.3。对于老系统可用bcc-tools中的tcpconnect.py替代功能相同只是编译方式不同。抓包是网络工程师的听诊器eBPF是CT扫描仪。前者告诉你“有杂音”后者告诉你“是肺部结节还是心脏瓣膜问题”。掌握两者你才能真正掌控TCP的命运。7. 给新手的三条血泪经验少走三年弯路最后分享我在某高校实验室带学生做网络实验时被反复验证的三条经验。它们不是技巧而是认知框架的校准7.1 经验一永远先抓“失败”的包再抓“成功”的包新手总想先抓一个完美的三次握手证明自己“会了”。但真实世界里90%的问题出在“不完美”的地方。我要求所有学生第一课必须抓一个必然失败的连接比如curl http://192.168.1.999:8080不存在的IP或nc -zv 192.168.1.20 9999未监听端口。然后在Wireshark里找RST包、ICMP Destination Unreachable包、超时重传包。为什么因为失败包暴露了协议栈的决策逻辑。你看到SYN重传3次后放弃就明白了RTO指数退避看到ICMP错误就懂了IP层如何反馈看到RST就知悉了socket状态机如何响应。这些比100个完美握手更有教学价值。7.2 经验二学会“倒着读”WiresharkWireshark默认按时间顺序显示包但排错时你要养成“倒着读”的习惯。比如HTTP请求失败不要从第一个SYN包开始看而是找到最后一个包通常是RST或ICMP右键 → “Follow” → “TCP Stream”看整个流的交互在流窗口里从底部往上翻找第一个异常信号如服务端发的RST或客户端发的FIN后没ACK。这就像破案先找到尸体再找凶器最后追查凶手。时间顺序是上帝视角而倒序阅读是侦探视角。7.3 经验三把Wireshark当“协议翻译器”而不是“包播放器”很多人把Wireshark当视频播放器只看包的流动。高手把它当翻译器关注每个字段的语义。比如tcp.window_size_value是原始值而tcp.window_size是计算后的实际窗口乘以WSCALEtcp.time_delta是包间时间差tcp.time_relative是距抓包开始的时间tcp.analysis.ack_rtt是Wireshark估算的RTT它基于ACK包的tcp.time_relative减去对应数据包的tcp.time_relative。在某次调试中我发现tcp.analysis.ack_rtt显示RTT为500ms但ping只有10ms。深入看tcp.time_relative发现是服务端应用层处理慢time.sleep(2)导致ACK延迟发出。Wireshark的RTT字段其实包含了应用层延迟这就是“翻译”出来的真相。所以

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑