TCP/IP 协议栈
TCP/IP 四层模型
各层核心职责
| 层级 | 协议单位 | 核心协议 | 运维场景 |
|---|---|---|---|
| 应用层 | 报文 | HTTP、DNS、SSH | Nginx 配置、域名解析、远程管理 |
| 传输层 | 段 (Segment) | TCP、UDP | 端口映射、连接排查、负载均衡 |
| 网络层 | 包 (Packet) | IP、ICMP | 路由、子网划分、VPN |
| 链路层 | 帧 (Frame) | Ethernet | 网卡 bonding、VLAN、ARP |
TCP 协议
三次握手
为什么是三次而不是两次?
- 两次握手无法确认客户端的接收能力
- 防止已失效的连接请求到达服务端,造成资源浪费
- 三次是建立可靠连接所需的最少次数
四次挥手
为什么是四次而不是三次?
- TCP 是全双工协议,每个方向的关闭需要独立确认
- 被动关闭方收到 FIN 后,可能还有数据未发完,不能立即关闭
TCP 状态机
TIME_WAIT 是运维高频问题
大量 TIME_WAIT 连接会耗尽端口资源:
# 查看 TIME_WAIT 连接数
ss -s
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
# 优化内核参数(/etc/sysctl.conf)
net.ipv4.tcp_tw_reuse = 1 # 允许复用 TIME_WAIT 连接
net.ipv4.tcp_fin_timeout = 30 # 缩短 FIN_WAIT_2 超时(默认 60s)
net.ipv4.tcp_max_tw_buckets = 5000 # 限制 TIME_WAIT 最大数量
net.ipv4.ip_local_port_range = 1024 65535 # 扩大端口范围
# 使设置生效
sysctl -p
TCP 重传与拥塞控制
TCP 通过以下机制保证可靠传输:
| 机制 | 说明 | 运维影响 |
|---|---|---|
| 超时重传 | RTO 计时器超时后重发 | 高延迟网络下需调整 |
| 快速重传 | 收到 3 个重复 ACK 立即重发 | 减少等待时间 |
| 滑动窗口 | 控制发送速率 | 影响吞吐量 |
| 拥塞控制 | 慢启动 → 拥塞避免 → 快重传 → 快恢复 | 影响带宽利用率 |
# 查看当前拥塞控制算法
sysctl net.ipv4.tcp_congestion_control
# cubic(Linux 默认)、bbr(Google 推荐)
# 启用 BBR 拥塞控制(提升带宽利用率)
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
# 验证
sysctl net.ipv4.tcp_congestion_control
# net.ipv4.tcp_congestion_control = bbr
BBR vs CUBIC
- CUBIC:基于丢包的拥塞控制,适合低延迟网络
- BBR:基于带宽估计的拥塞控制,在高延迟、有丢包的网络中表现更好
- 云服务器推荐使用 BBR,尤其是跨境网络
UDP 协议
| 特性 | TCP | UDP |
|---|---|---|
| 连接方式 | 面向连接 | 无连接 |
| 可靠性 | 可靠传输 | 不保证可靠 |
| 有序性 | 保证顺序 | 不保证顺序 |
| 速度 | 较慢(开销大) | 快(开销小) |
| 头部大小 | 20-60 字节 | 8 字节 |
| 应用场景 | HTTP、SSH、数据库 | DNS、NTP、视频流、游戏 |
IP 协议
IPv4 地址与子网
# 查看 IP 地址
ip addr show
# IP 地址组成:网络部分 + 主机部分
# 192.168.1.100/24
# 网络部分:192.168.1.0
# 主机部分:.100
# 子网掩码:255.255.255.0
# 常见私有地址范围
# A 类:10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
# B 类:172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
# C 类:192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
子网划分速算
| CIDR | 子网掩码 | 主机数 | 常用场景 |
|---|---|---|---|
| /32 | 255.255.255.255 | 1 | 单主机路由 |
| /30 | 255.255.255.252 | 2 | 点对点链路 |
| /28 | 255.255.255.240 | 14 | 小型 DMZ |
| /24 | 255.255.255.0 | 254 | 标准局域网 |
| /16 | 255.255.0.0 | 65534 | 大型 VPC |
ICMP 协议
# ping - 测试连通性(ICMP Echo Request / Echo Reply)
ping -c 4 8.8.8.8
# traceroute - 跟踪路由路径(ICMP TTL exceeded)
traceroute 8.8.8.8
# mtr - 综合 ping + traceroute,持续监测
mtr 8.8.8.8
ARP 协议
ARP(Address Resolution Protocol)将 IP 地址解析为 MAC 地址:
# 查看 ARP 缓存
arp -n
ip neigh show
# 清除 ARP 缓存
ip neigh flush all
# ARP 欺骗防御
# 静态绑定关键网关的 MAC
arp -s 192.168.1.1 aa:bb:cc:dd:ee:ff
常用网络诊断命令
分层诊断法
关键命令速查
# === 连通性测试 ===
ping -c 4 targethost # ICMP 连通性
traceroute targethost # 路由路径
mtr --report targethost # 持续路由监测
# === 端口测试 ===
telnet targethost 80 # 测试 TCP 端口
nc -zv targethost 80 # netcat 端口扫描
nc -zv targethost 80-90 # 端口范围扫描
ss -tlnp # 查看监听端口
ss -antp | grep ESTABLISHED # 查看已建立连接
# === DNS 测试 ===
dig example.com # DNS 查询
dig +trace example.com # 完整解析链路
nslookup example.com # 简单 DNS 查询
# === HTTP 测试 ===
curl -v https://example.com # HTTP 详细请求
curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" URL # 状态码和耗时
# === 抓包 ===
tcpdump -i eth0 port 80 # 抓取 80 端口流量
tcpdump -i any host 10.0.0.1 -w capture.pcap # 保存抓包文件
运维常见网络配置
MTU 与 MSS
# 查看 MTU
ip link show eth0 # 默认 1500
# 测试路径 MTU(发送不允许分片的包)
ping -M do -s 1472 targethost # 1472 + 28(IP+ICMP头) = 1500
# 修改 MTU(VPN/隧道场景常需调小)
ip link set eth0 mtu 1400
MTU 与隧道
- 标准以太网 MTU = 1500
- VPN/GRE 隧道需减去封装头(通常设为 1400)
- VXLAN overlay 通常需要 MTU = 1550+
- MTU 不匹配会导致大包传输失败
TCP Keepalive
# 查看 TCP Keepalive 配置
sysctl net.ipv4.tcp_keepalive_time # 空闲多久开始探测(默认 7200s)
sysctl net.ipv4.tcp_keepalive_intvl # 探测间隔(默认 75s)
sysctl net.ipv4.tcp_keepalive_probes # 探测次数(默认 9)
# 优化配置(缩短无效连接检测时间)
sysctl -w net.ipv4.tcp_keepalive_time=600
sysctl -w net.ipv4.tcp_keepalive_intvl=30
sysctl -w net.ipv4.tcp_keepalive_probes=3
常见面试问题
Q1: TCP 三次握手的过程?为什么不能两次?
答案:
三次握手过程:
- 客户端发 SYN(seq=x),进入 SYN_SENT
- 服务端收到后回 SYN+ACK(seq=y, ack=x+1),进入 SYN_RCVD
- 客户端回 ACK(ack=y+1),双方进入 ESTABLISHED
不能两次的原因:
- 防止历史连接:如果网络中存在延迟的旧 SYN 包,两次握手会导致服务端误以为建立了新连接,浪费资源
- 确认双方收发能力:两次握手只能确认客户端的发送能力和服务端的收发能力,无法确认客户端的接收能力
Q2: 大量 TIME_WAIT 怎么处理?
答案:
TIME_WAIT 出现在主动关闭连接的一方,持续 2MSL(Linux 默认 60s)。大量 TIME_WAIT 常见于频繁短连接场景(如 HTTP 1.0)。
排查:
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
解决方案:
- 启用 tcp_tw_reuse:
net.ipv4.tcp_tw_reuse = 1,允许复用 TIME_WAIT 连接 - 缩短 FIN 超时:
net.ipv4.tcp_fin_timeout = 30 - 扩大端口范围:
net.ipv4.ip_local_port_range = 1024 65535 - 使用长连接:HTTP Keep-Alive、连接池
- 负载均衡层处理:让 LB 作为连接代理
注意
不推荐使用 tcp_tw_recycle,在 NAT 环境下会导致连接异常,Linux 4.12+ 已移除此参数。
Q3: TCP 和 UDP 的区别?各自的应用场景?
答案:
| 维度 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接 | 无连接 |
| 可靠性 | 保证可靠、有序 | 不保证 |
| 拥塞控制 | 有 | 无 |
| 传输效率 | 较低 | 高 |
| 头部开销 | 20-60 字节 | 8 字节 |
应用场景:
- TCP:HTTP(S)、SSH、FTP、MySQL、Redis
- UDP:DNS(查询)、NTP、DHCP、视频直播、游戏、QUIC (HTTP/3)
Q4: 如何排查服务端口不通?
答案:
分层排查:
- 服务是否监听:
ss -tlnp | grep PORT - 本地防火墙:
iptables -L -n/firewall-cmd --list-all - 安全组(云环境):检查入站规则
- 网络连通性:
telnet host port/nc -zv host port - 路由问题:
traceroute host - 抓包确认:
tcpdump -i any port PORT
Q5: BBR 和 CUBIC 拥塞控制的区别?
答案:
- CUBIC(Linux 默认):基于丢包的拥塞控制,发生丢包时降低发送窗口。在低延迟、无丢包的局域网中表现良好,但在高延迟、有随机丢包的广域网中可能无法充分利用带宽。
- BBR(Google 提出):基于带宽和 RTT 估计的拥塞控制,不依赖丢包信号。在跨境网络、卫星链路等高延迟高丢包场景下,带宽利用率显著优于 CUBIC。
云服务器、CDN 节点推荐启用 BBR。