最准方法是tcpdump+tshark抓包分析三次握手时间戳,可精确到微秒;ss仅提供RTT估算值,适合运维巡检;bpftrace可低开销实时监控握手延迟分布;应用层工具如curl无法分离纯TCP握手各阶段耗时。

用 tcpdump + tshark 分析 TCP 握手耗时
直接看三次握手各段延迟,tcpdump 抓包配合 tshark 是最准的——因为绕过了内核统计偏差,能精确到微秒级。别指望 ss 或 netstat,它们只给连接状态,不记录时间戳。
实操建议:
- 先用
tcpdump -i any -w handshake.pcap port 80 or port 443抓包(注意加-w写文件,别用-v实时打印,会丢包) - 用
tshark -r handshake.pcap -Y "tcp.flags.syn == 1 || tcp.flags.ack == 1" -T fields -e frame.time_epoch -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e tcp.flags.syn -e tcp.flags.ack提取关键帧时间戳和标志位 - 按
ip.src+ip.dst+tcp.srcport+tcp.dstport四元组配对 SYN、SYN-ACK、ACK,计算SYN-ACK - SYN(服务端响应延迟)、ACK - SYN-ACK(客户端确认延迟)
用 ss + awk 统计已建立连接的握手估算值
ss 本身不存握手时间,但它的 rtt 字段(来自 TCP_INFO)能间接反映链路往返延迟,对大量连接做粗粒度分布分析够用——适合运维巡检,不适合单次故障定位。
常见错误现象:执行 ss -i 却看不到 rtt 列,是因为没加 -t(TCP)或连接未处于 ESTAB 状态。
实操建议:
- 运行
ss -tien state established | awk '{print $7}' | grep -o 'rtt:[0-9]*' | cut -d: -f2 | sort -n | uniq -c,输出 rtt 毫秒值频次分布 - 注意
rtt是当前连接的平滑估计值,不是单次握手耗时;若连接刚建好,该值可能为 0 或极小,需等几次数据包交互后才稳定 - 该方法无法区分 SYN 耗时和服务端处理耗时,仅反映网络层+协议栈整体延迟
用 eBPF 工具 bpftrace 实时观测 SYN/ACK 时间差
如果需要无侵入、低开销地长期监控握手耗时分布,bpftrace 是目前最实用的选择——它直接 hook 内核 TCP 状态机,比用户态抓包更轻量,且支持直方图聚合。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
使用场景:排查偶发性高延迟握手(比如 TLS 前置握手卡顿),或对比不同服务器的内核协议栈行为差异。
实操建议:
- 安装
bpftrace后运行:bpftrace -e ' kprobe:tcp_v4_connect { @start[tid] = nsecs; } kretprobe:tcp_v4_connect /@start[tid]/ { $d = nsecs - @start[tid]; @handshake_us = hist($d / 1000); delete(@start[tid]); }' - 注意:该脚本只捕获主动连接(客户端侧),如需服务端侧,改用
kprobe:tcp_rcv_state_process并过滤tcp_state == TCP_SYN_RECV - 输出是微秒级直方图,单位是 us;若发现大量 >100000(即 100ms),大概率是服务端 accept 队列满或负载过高
为什么不用 curl -w 或应用层日志
应用层测得的“握手时间”其实是 connect() 系统调用返回耗时,包含 DNS 解析、路由查找、重传等待等,不是纯 TCP 三次握手耗时。尤其在 DNS 缓存未命中或网络丢包时,误差可达数百毫秒。
容易踩的坑:
-
curl -w "%{time_connect}"的值受SO_RCVBUF设置影响——缓冲区太小会导致 connect() 等待 ACK 超时重发,把 100ms 延迟误报成 300ms+ - Go 的
http.Transport.DialContext默认启用 keep-alive,复用连接时time_connect为 0,完全无法反映真实握手分布 - 所有应用层工具都无法分离 SYN 发出时刻与 SYN-ACK 收到时刻,因此不能用于定位是客户端发包慢,还是服务端回包慢
真要拆解握手瓶颈,必须回到网络层或内核层——抓包看时间戳,或者用 eBPF 打点,少走应用层弯路。

















