飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • IP协议

    • 认识 IP 协议与网络层定位
    • IPv4 编址体系与分类地址
    • CIDR 与子网划分实战
    • IPv6 编址体系
    • ARP 协议详解
    • NDP 协议详解
    • IGMP 与 MLD 组播侦听发现
    • VRRP 与网关冗余
    • IPv4 数据报首部解析
    • IPv6 数据报与扩展首部
    • IPsec 安全扩展
    • 分片、MTU 与路径发现
    • ICMP 与 Traceroute 原理
    • 路由基础与转发流水线
    • 动态路由协议
    • NAT 网络地址转换
    • DHCP 与自动配置
    • Wireshark 与命令行工具
    • IPv6 过渡技术
    • IP 协议栈排障与攻击防御
  • TCP协议

    • 认识 TCP 协议与传输层定位
    • TCP 报文段首部解析
    • 三次握手与连接建立
    • 四次挥手与连接释放
    • TCP 有限状态机
    • 序列号与确认机制
    • 超时重传与 RTO 计算
    • 滑动窗口与流量控制
    • 拥塞控制基础
    • 现代拥塞控制算法
    • TCP 选项与扩展
    • TCP 性能调优与内核参数
    • Nagle 算法与糊涂窗口综合征
    • TCP 定时器与 Keep-Alive 机制
    • TCP 安全与攻击防御
    • TCP 与上层/下层交互
    • TCP 综合实践与排障

TCP 综合实践与排障

Wireshark 深度分析

完整通信流分析

场景:访问 https://www.example.com

Wireshark 过滤表达式

tcp.port == 443              # 443 端口的 TCP 流量
tcp.stream eq 0              # 第 0 条 TCP 流
tcp.flags.syn == 1           # SYN 报文
tcp.flags.fin == 1           # FIN 报文
tcp.analysis.retransmission  # 重传报文
tcp.analysis.duplicate_ack    # 重复 ACK
tcp.options.sack              # 带 SACK 的报文
tcp.window_size_value < 1000  # 小窗口通告

常见 TCP 排障场景

场景 1:连接建立失败

现象:telnet target 443 卡住,或立即返回 Connection Refused

排查:
1. ping target → 通?网络层正常
2. telnet target 443 → Connection Refused?端口未监听
3. telnet target 443 → 卡住?防火墙拦截或路由问题
4. Wireshark 抓包:
   - 看到 SYN 无回复?防火墙 DROP 或路由不可达
   - 看到 SYN + RST?端口未监听
   - 看到 SYN + SYN-ACK 无 ACK?客户端问题

场景 2:连接建立后传输极慢

现象:能 ping 通,但网页加载慢、下载速度低

排查:
1. 检查 RTT:ping target,RTT 是否异常高?
2. 检查丢包:mtr target,哪一跳丢包?
3. 检查窗口:Wireshark 看 Window Size,是否太小?
4. 检查重传:Wireshark 过滤 tcp.analysis.retransmission,重传率是否高?
5. 检查拥塞:ss -ti 看 cwnd 和 ssthresh

场景 3:大量 CLOSE_WAIT

现象:ss -tan | grep CLOSE-WAIT | wc -l 数值很大

原因:服务端收到客户端 FIN 后,应用层没有及时 close()

排查:
1. ss -tp | grep CLOSE-WAIT → 找到对应进程
2. 检查应用代码:是否在读取完数据后忘记关闭连接?
3. 检查线程池:是否线程耗尽导致无法处理关闭?

场景 4:TIME_WAIT 过多

现象:端口耗尽,无法建立新连接

排查:
1. ss -tan | grep TIME-WAIT | wc -l
2. 确认是服务端还是客户端主动关闭
3. 优化:Keep-Alive / 连接池 / 让客户端主动关闭

Socket 编程关键 API

// 服务端
int listen(int sockfd, int backlog);    // backlog: 全连接队列长度
int accept(int sockfd, ...);            // 从全连接队列取连接

// 客户端
int connect(int sockfd, ...);           // 触发三次握手

// 数据收发
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

// 关闭
int close(int sockfd);                  // 完全关闭(四次挥手)
int shutdown(int sockfd, int how);        // 半关闭
    // SHUT_RD: 关闭读
    // SHUT_WR: 关闭写(发送 FIN)
    // SHUT_RDWR: 双向关闭

// 选项设置
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));    // 禁用 Nagle
setsockopt(sockfd, IPPROTO_TCP, TCP_QUICKACK, &on, sizeof(on));    // 禁用延迟 ACK

性能测试工具

# iperf3: 测试 TCP 吞吐量
# 服务端
iperf3 -s
# 客户端
iperf3 -c <server_ip> -t 30 -i 1

# nc (netcat): 简单 TCP 测试
nc -vz target_ip port    # 端口连通性测试
nc -l 8080               # 监听 8080
nc target_ip 8080        # 连接并发送数据

# hping3: 构造自定义 TCP 报文
hping3 -S -p 80 target_ip          # SYN 扫描
hping3 -A -p 80 target_ip          # ACK 扫描
hping3 -S -p 80 --flood target_ip  # SYN Flood(测试环境!)

# ss: 查看连接状态
ss -s                    # 统计摘要
ss -tan                  # 所有 TCP 连接
ss -ti                   # 详细信息(含 cwnd、rtt)
ss -tp                   # 显示进程

# tc: 模拟网络条件
sudo tc qdisc add dev eth0 root netem delay 100ms loss 1%
sudo tc qdisc del dev eth0 root

核心参数速查表

参数查看命令典型调优
拥塞控制算法sysctl net.ipv4.tcp_congestion_controlcubic / bbr
SYN Cookiesysctl net.ipv4.tcp_syncookies1
SACKsysctl net.ipv4.tcp_sack1
窗口缩放sysctl net.ipv4.tcp_window_scaling1
时间戳sysctl net.ipv4.tcp_timestamps1
ECNsysctl net.ipv4.tcp_ecn2
TFOsysctl net.ipv4.tcp_fastopen3
tw_reusesysctl net.ipv4.tcp_tw_reuse1
fin_timeoutsysctl net.ipv4.tcp_fin_timeout30
somaxconnsysctl net.core.somaxconn65535
max_syn_backlogsysctl net.ipv4.tcp_max_syn_backlog65536

本篇小结

  • Wireshark 过滤:tcp.stream、tcp.analysis.retransmission、tcp.flags.syn
  • 排障分层:物理 → 链路 → 网络(ping)→ 传输(telnet/Wireshark)→ 应用
  • CLOSE_WAIT:应用层未 close(),检查代码
  • TIME_WAIT:主动关闭方问题,用 Keep-Alive/连接池解决
  • 工具链:iperf3 / nc / hping3 / ss / tc
  • 核心参数:拥塞控制算法、SYN Cookie、窗口缩放、TFO

动手实践

  1. 用 Wireshark 抓取一次完整 HTTPS 访问,标记:

    • 三次握手的 SYN/SYN-ACK/ACK
    • TLS ClientHello/ServerHello
    • 数据传输的 PSH+ACK
    • 四次挥手的 FIN/ACK
  2. 用 iperf3 测试本机到路由器的 TCP 吞吐:

    # 服务端
    iperf3 -s
    # 客户端
    iperf3 -c 192.168.1.1 -t 30
    
  3. 用 tc 模拟 100ms 延迟 + 1% 丢包,观察对 TCP 吞吐的影响:

    sudo tc qdisc add dev eth0 root netem delay 100ms loss 1%
    iperf3 -c <server> -t 30
    sudo tc qdisc del dev eth0 root
    
  4. 查看本机所有 TCP 内核参数:

    sysctl -a | grep tcp
    
  5. 思考:为什么 ss -ti 显示的 cwnd 值在不同连接中差异很大?cwnd 与 RTT、带宽之间有什么关系?

上一页
TCP 与上层/下层交互