🔧 知识点 1:TCP 三次握手
一句话: 建立 TCP 连接需要 3 次包交互(SYN → SYN+ACK → ACK),核心目的是双方都确认自己的收发能力正常。
客户端 服务端
│ ──── SYN (seq=x) ────────▶ │ 我要连你
│ ◀─── SYN+ACK (seq=y, ──── │ 收到了,我也要连你
│ ack=x+1) │
│ ──── ACK (ack=y+1) ─────▶ │ 收到了,建立连接
│ │
═══════ 连接建立 ═══════
# 实时观察握手过程(抓 SYN 包)
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'
⚠️ 易错点 :
为什么不是两次?------两次握手服务端无法确认"自己发的包客户端能收到"。经典面试题:两次握手会导致旧的历史连接被误建立(网络中滞留的旧 SYN 到达服务端,服务端直接建连,资源被白白占用)。
🔧 知识点 2:TCP 四次挥手
一句话: 断开连接需要 4 次交互(FIN → ACK → FIN → ACK),比握手多一次是因为** TCP 全双工**,两边要各自单独关闭发送通道。
主动方(通常是客户端) 被动方(服务端)
│ ──── FIN ───────────────▶ │ 我说完了
│ ◀─── ACK ──────────────── │ 知道了(但我可能还没说完)
│ (等待被动方发完数据) │
│ ◀─── FIN ──────────────── │ 我也说完了
│ ──── ACK ───────────────▶ │ 好的,关闭
│ │
→ TIME_WAIT 等待 2MSL → → CLOSE
⚠️ 易错点 :
谁先调用
close()谁进TIME_WAIT。服务端频繁主动断开连接(如 HTTP 超时主动 close)会导致服务端堆积大量 TIME_WAIT------这是反向代理/Nginx 长连接配置不当的典型症状。
🔧 知识点 3:TIME_WAIT 状态
一句话: 主动关闭方在发送最后一个 ACK 后进入 TIME_WAIT,等待 2 个 MSL(Linux 上固定 60 秒),目的是让旧报文在网络中自然消亡 + 确保对方收到了最后的 ACK。
# 统计 TIME_WAIT 数量
ss -ant | awk '{print $1}' | sort | uniq -c
# 查看 TIME_WAIT 相关内核参数
sysctl net.ipv4.tcp_tw_reuse
cat /proc/sys/net/ipv4/tcp_fin_timeout
# 高并发场景推荐配置(/etc/sysctl.conf)
net.ipv4.tcp_tw_reuse = 1 # 允许复用 TIME_WAIT 端口(仅出站连接)
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_fin_timeout = 30
⚠️ 易错点 :
TIME_WAIT 多 ≠ 一定是问题,几万个以内属正常
不要开
tcp_tw_recycle(内核 4.12 后已删除,NAT 环境会丢连接)根治方法:用长连接(HTTP keep-alive、连接池),而不是调内核参数
🔧 知识点 4:netstat vs ss
一句话: netstat 是老工具(遍历 /proc,慢),ss 是替代品(直接读内核 socket,快一个量级),生产排查优先用 ss。
# 老命令 → 新命令对照
netstat -ant → ss -ant # 所有 TCP 连接
netstat -antp → ss -antp # 带进程信息
netstat -lnp → ss -lnp # 监听端口
# 常用实战
ss -s # 连接状态总览
ss -ant state time-wait | wc -l # TIME_WAIT 数量
ss -tnp state established '( dport = :443 )' # 到 443 的活跃连接
# 统计各状态连接数
ss -ant | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn
⚠️ 易错点:
上万台连接的服务器上
netstat -antp可能卡住几十秒,ss秒出。另外ss不带-p时不需要 root,加了才需要------排查时先不带 -p 快速看全貌,再带 -p 定位进程。
🔧 知识点 5:tcpdump 抓包实战
一句话: tcpdump 是命令行抓包神器,配合 Wireshark 分析是网络排障的"终极手段"------日志会骗人,抓包不会。
# 基础语法:tcpdump -i 网卡 过滤条件
tcpdump -i eth0 -nn port 80 # 抓 80 端口
tcpdump -i eth0 -nn host 10.0.0.5 # 抓特定 IP 的包
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0' # 抓 RST 包
# 保存为文件,用 Wireshark 打开
tcpdump -i eth0 -nn -w /tmp/capture.pcap port 443
# 常用组合:抓 HTTP 请求头
tcpdump -i eth0 -nn -A 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'
# 0x47455420 = "GET "
# 抓三次握手失败(只有 SYN 没有 SYN+ACK)
tcpdump -i eth0 -nn 'dst port 3306 and tcp[tcpflags] & tcp-syn != 0'
⚠️ 易错点 :
"服务连不上"排障三板斧:
ping(网络层通不通)→telnet/nc(端口通不通)→tcpdump(包到底发没发、对方回没回)。RST 包出现 = 对端明确拒绝(端口没监听或被防火墙 REJECT)。
🔧 知识点 6:DNS 解析链路
一句话: 域名解析顺序是 本地 hosts → 本地缓存 → /etc/resolv.conf 指定的 DNS 服务器 → 逐级递归查询,任何一环出错都会"网络正常但域名不通"。
# 排查 DNS 问题的命令链
cat /etc/hosts # 第一步:检查 hosts 劫持
cat /etc/resolv.conf # 第二步:确认 DNS 服务器配置
dig www.example.com # 完整解析过程(推荐)
dig +trace www.example.com # 显示逐级递归查询
dig @8.8.8.8 www.example.com # 指定 DNS 服务器查询
nslookup www.example.com # 老命令,兼容 Windows
# 常见解析记录类型
dig example.com A # IPv4
dig example.com AAAA # IPv6
dig example.com CNAME # 别名
dig example.com MX # 邮件
dig -x 8.8.8.8 # 反向解析(IP → 域名)
⚠️ 易错点 :
curl IP 通、curl 域名不通 = DNS 问题 。容器/K8s 环境高发:CoreDNS 挂了、
/etc/resolv.conf的ndots:5导致所有域名都先走集群内 DNS 查询,性能急剧下降。
🔧 知识点 7:HTTP 状态码与排障
一句话: HTTP 状态码分五类(1xx 信息 / 2xx 成功 / 3xx 重定向 / 4xx 客户端错 / 5xx 服务端错),运维重点关注 5xx 和 499。
# 快速测试 HTTP 响应
curl -v http://example.com # 看完整请求/响应头
curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" http://example.com
# 常见状态码速查
# 200 OK 正常
# 301/302 永久/临时重定向
# 400 Bad Request 请求格式错误
# 401/403 未认证 / 被拒绝(权限)
# 404 Not Found 资源不存在
# 499 客户端等不及主动断开(Nginx 特有,后端太慢)
# 502 Bad Gateway 后端挂了/连不上 upstream
# 504 Gateway Timeout 后端超时
# Nginx 统计各状态码数量
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
⚠️ 易错点 :
502 vs 504 是面试高频:502 = 后端进程挂了或拒绝连接(check
systemctl status/ 端口);504 = 后端活着但太慢(check 慢查询、上游超时配置)。499 大量出现 = 用户侧体验已经崩了,比 5xx 更隐蔽。
🔧 知识点 8:iptables / firewalld 防火墙基础
一句话: iptables 按 四表五链 处理数据包(filter 表最常用,INPUT/OUTPUT/FORWARD 三大链),规则从上往下匹配,命中即停。
# 查看规则(带序号)
iptables -L -n --line-numbers
# 放行 SSH(插到第 1 位,避免被 DROP 规则挡住)
iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
# 放行 80/443
iptables -I INPUT 1 -p tcp -m multiport --dports 80,443 -j ACCEPT
# 封禁 IP
iptables -I INPUT 1 -s 203.0.113.50 -j DROP
# 删除第 3 条规则
iptables -D INPUT 3
# CentOS 7+ 用 firewalld(底层还是 iptables/nftables)
firewall-cmd --list-all
firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --reload
⚠️ 易错点 :
经典自锁事故:
iptables -A INPUT -j DROP(默认追加到末尾)之前忘了放行 22 端口------SSH 直接断线,只能去机房/控制台。永远用-I(插入头部)放行 SSH,改完规则先用iptables -L确认再继续操作。
🔧 知识点 9:端口占用与监听排查
一句话: "Address already in use" 报错的本质是端口已被其他进程监听(或处于 TIME_WAIT 未释放),排查思路是:找进程 → 杀/换端口。
# 谁占用了 8080?(推荐)
ss -lnp | grep :8080
lsof -i :8080
# Windows 环境对应命令
netstat -ano | findstr :8080 # 拿到 PID
tasklist /fi "PID eq 12345" # 查进程名
# 杀掉占端口的进程
kill -9 <PID>
# 换个思路:让服务复用端口(代码层面)
# socket 设置 SO_REUSEADDR(大多数框架已默认开启)
# 查看端口监听范围
cat /proc/sys/net/ipv4/ip_local_port_range # 临时端口范围 32768-60999
⚠️ 易错点:
容器场景高发:容器内进程监听 127.0.0.1 而不是 0.0.0.0 ,导致外部/其他容器死活连不上。Docker 端口映射只转发到容器 IP,不会转发到容器内的 localhost。
ss -lnp看监听地址:127.0.0.1:8080外部不可达,0.0.0.0:8080才对外。
🔧 知识点 10:curl / wget / nc 排障三板斧
一句话: curl 测 HTTP、nc 测 TCP 端口、wget 下载文件,三个工具组合覆盖 90% 的网络连通性排查。
# curl:测 HTTP,-w 输出关键指标
curl -o /dev/null -s -w "DNS:%{time_namelookup}s 连接:%{time_connect}s \
首字节:%{time_starttransfer}s 总耗时:%{time_total}s\n" http://example.com
# curl:带 Host 头测试(绕过 DNS,直接打后端)
curl -H "Host: api.example.com" http://10.0.0.5/health
# nc:测端口连通性
nc -zv 10.0.0.5 3306 # 只测握手
nc -l 9999 # 起一个临时监听(配合另一台机器 nc 测连通)
# telnet:nc 不在时的备选
telnet 10.0.0.5 3306
# wget:断点续传下载
wget -c https://example.com/bigfile.tar.gz
⚠️ 易错点 :
慢在哪?看
time_starttransfer与time_connect的差值:差值大 = 服务端处理慢 (应用/数据库瓶颈);time_connect本身就大 = 网络延迟或握手问题 。-H "Host: xxx"绕过 DNS 直打后端,是**区分"DNS 问题"还是"服务问题"**的关键技巧。
📋 知识点速查表
| # | 主题 | 一句话 |
|---|---|---|
| 1 | 三次握手 | 两次握手的坑:旧 SYN 会建立历史连接 |
| 2 | 四次挥手 | 全双工,两边各关各的,所以多一次 |
| 3 | TIME_WAIT | 2MSL=60s,多≠有病,根治靠长连接 |
| 4 | ss vs netstat | 生产环境无脑用 ss |
| 5 | tcpdump | 日志会骗人,抓包不会 |
| 6 | DNS | IP 通域名不通,先查 DNS |
| 7 | HTTP 状态码 | 502 后端挂,504 后端慢,499 用户跑了 |
| 8 | iptables | 永远 -I 放行 SSH 在最前面 |
| 9 | 端口占用 | 监听 127.0.0.1 外部不可达,要 0.0.0.0 |
| 10 | 排障三板斧 | ping → nc → curl,逐层定位 |