ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

计算机网络基础知识实战:TCP状态机、三次握手与CLOSE_WAIT排障指南

计算机网络基础知识实战:TCP状态机、三次握手与CLOSE_WAIT排障指南 简介这份PDF资料面向准备技术面试的IT求职者与网络初学者系统梳理计算机网络核心考点帮助读者在面试与工程实践中快速定位知识盲区。内容围绕OSI七层参考模型与TCP/IP四层模型展开涵盖TCP/IP协议族、TCP/UDP/SCTP协议对比、三次握手与四次挥手、TCP状态机、TIME_WAIT状态、端口号、超时重传与快速重传、TCP Header结构、可靠传输、流量控制与拥塞控制以及IPv4/IPv6、ICMP、ARP、IGMP等网络层协议并附有常见面试问题解析。资源包为1个PDF文件大小约2.08MB结构清晰、便于按章节检索复习。目前已有969人学习下载适合需要系统梳理网络知识体系、查漏补缺或冲刺面试的读者参考使用。1. 从一次线上故障说起为什么我又把计算机网络基础知识翻出来重啃上周排查一个服务端连接数暴涨的问题netstat里满屏的CLOSE_WAIT第一反应是代码没关连接翻到一半发现是上游超时策略和 TCP 四次挥手的状态迁移对不上。这种时候你才会意识到OSI 七层模型、TCP/IP 四层模型、三次握手四次挥手这些计算机网络基础知识不是面试前背一背就完事的考点而是排障时真正能救命的东西。这份资源把网络模型、TCP/IP 协议族、TCP/UDP/SCTP 对比、TCP 状态机、TIME_WAIT、超时重传与快速重传、流量控制和拥塞控制串成了一条线适合两类人一是准备面试、需要把零散知识点串成体系的人二是日常写后端、做网络编程遇到连接异常想快速定位的人。它不教你写业务代码但能让你在看抓包、读内核参数、调 socket 选项时知道自己在改什么、为什么改。2. 网络模型怎么选OSI 七层与 TCP/IP 四层的映射关系和协议归属2.1 两张模型图不是二选一而是理论与工程的对照表很多人背 OSI 七层背得滚瓜烂熟一到实际抓包就懵因为工程里用的是 TCP/IP 四层模型。这份资料把两者的映射关系讲得很直白下两层物理层和数据链路层合并为数据链路层上三层会话层、表示层、应用层合并为应用层传输层和网络层保持不变。这么合并的理由也给了——上三层处理应用业务细节差异大下四层实现通信细节更通用而且上三层通常在用户进程内下四层作为 OS 内核的一部分提供。理解这个映射的实际价值在于当你用tcpdump抓包时看到的是以太网帧、IP 数据报、TCP 分节、应用层数据这四层对应关系清晰了排查问题时才能快速定位是哪一层出了状况。比如ping不通先看网络层 ICMP 有没有回包端口连不上看传输层 SYN 有没有响应HTTP 返回 502那大概率是应用层的事。2.2 协议族清单每个协议解决什么问题资料里把 TCP/IP 协议族按层拆开列了一遍我整理成表格方便对照层次协议核心作用典型场景传输层TCP面向连接、可靠、全双工字节流文件传输、HTTP 通信传输层UDP无连接、不可靠、数据报音视频、DNS 查询传输层SCTP面向连接、多流多宿、消息服务信令传输、高可靠场景网络层IPv432 位地址、路由选择当前主流网络网络层IPv6128 位地址、巨大地址空间新一代网络网络层ICMP主机与路由间消息通信ping、traceroute网络层ARPIPv4 地址映射为 MAC 地址广播网络寻址网络层IGMP组播通信管理视频组播这张表建议存下来面试被问到“TCP/IP 包含哪些协议”时按层说比按字母顺序背要清晰得多。资料里还特别提到工程实现中只需要重点关注传输层和应用层下两层由内核和网卡驱动处理这个视角对后端开发很实用。2.3 从套接字角度看模型分层资料里有一句话很关键套接字作为传输层以下网络的封装为上面三层提供了统一接口。这意味着你写socket()、bind()、listen()、accept()的时候实际上是在和传输层打交道下面的网络层和数据链路层被内核屏蔽了。理解这一点就能明白为什么设置SO_RCVBUF会影响 TCP 通告窗口为什么TCP_MAXSEG能控制分节大小——这些 socket 选项直接作用于传输层行为。3. TCP 连接全生命周期三次握手、四次挥手与状态机排障3.1 三次握手和四次挥手的本质差异资料用打电话的场景类比三次握手和四次挥手很直观。但真正需要理解的是为什么握手能合并 ACK 和 SYN挥手却要分开发三次握手中服务端收到 SYN 后既需要确认客户端的 SYN发 ACK又需要发送自己的 SYN这两个动作可以合在一个分节里完成因为服务端此时已经知道了客户端的初始序列号没有额外等待的必要。四次挥手不同TCP 是全双工的两端的关闭是独立动作。A 端发 FIN 表示“我没数据要发了”B 端回 ACK 表示“知道了”但 B 端可能还有数据要发给 A 端所以 B 端的 FIN 必须等自己的数据发完才能单独发送。这就是半关闭状态存在的原因。3.2 TCP 状态机排障时最该盯住的几个状态资料把服务端、客户端、主动关闭方、被动关闭方的状态迁移都列了出来。实际排障中高频出现且容易出问题的是这几个状态SYN_RCVD服务端收到 SYN 并发出 SYNACK 后进入此状态如果大量堆积通常是 SYN Flood 攻击或客户端 ACK 丢失。FIN_WAIT_2主动关闭方收到 ACK 后进入如果长期停留说明对端一直没发 FIN可能是对端应用没调close()。CLOSE_WAIT被动关闭方收到 FIN 并回 ACK 后进入如果大量堆积几乎可以确定是应用层没有正确关闭连接。TIME_WAIT主动关闭方最后经历的状态持续 2MSL用于保证最后一个 ACK 能重传、旧分节能在网络中消逝。提示CLOSE_WAIT堆积是代码问题TIME_WAIT堆积是协议正常行为两者排查方向完全不同不要搞混。3.3 用 ss 命令验证状态迁移光看理论不够实际验证一遍状态变化会记得更牢。开两个终端一个用nc监听一个用nc连接然后用ss观察# 终端1监听 9999 端口 nc -l 9999 # 终端2连接 nc 127.0.0.1 9999 # 终端3查看 TCP 连接状态 ss -tanp | grep 9999执行后你会看到ESTABLISHED状态的连接。此时在终端2按CtrlC关闭再执行ss -tanp | grep 9999就能看到主动关闭方进入TIME_WAIT被动关闭方短暂出现CLOSE_WAIT后消失。这个实验比背状态图有效得多。参数说明-t只看 TCP-a显示所有状态-n不解析服务名-p显示进程信息。如果TIME_WAIT太多影响端口复用可以调整内核参数net.ipv4.tcp_tw_reuse但生产环境慎用资料里也强调了TIME_WAIT存在的必要性。4. 可靠传输与重传机制从 ARQ 到快速重传的落地理解4.1 ARQ 三种模式的递进关系资料把 ARQ 协议拆成停等 ARQ、连续 ARQ、反馈 ARQ 三种模式这个递进逻辑很清楚停等 ARQ 发一个等一个性能差连续 ARQ 连续发多个再等确认其中 Go-Back-N 出错时重传整个窗口Selective-Repeat 只重传出错的分组反馈 ARQ 则是接收方周期性发确认。Kafka 在应用层确保消息一致性时也用了类似 Continuous ARQ 和 Feedback ARQ 的机制这个类比很有价值——说明传输层的可靠传输思想会向上渗透到应用层设计中。4.2 超时重传和快速重传的触发条件超时重传靠定时器RTO 根据 RTT 动态调整一般至少为 1.5 倍 RTT。RTO 太小会导致频繁重传太大会导致等待过久。快速重传靠重复 ACK发送方连续收到 3 次重复确认就立即重传不用等超时。资料里给了一个数据传输时间估算的例子用ping测平均 RTT 为 175ms发送 2000 字节数据每次 40 字节共 50 次估算耗时 8750ms。这个估算方法虽然粗糙但在没有专业工具时能快速判断传输耗时是否合理。4.3 用 Python 模拟滑动窗口发送理解滑动窗口最好的方式是写一段模拟代码。下面用 Python 模拟一个简化的 Go-Back-N 发送方# 模拟 Go-Back-N 发送方滑动窗口 WINDOW_SIZE 4 # 窗口大小 BASE 0 # 窗口基序号 NEXT_SEQ 0 # 下一个待发送序号 TOTAL 10 # 总分组数 def send_packet(seq): 模拟发送分组返回是否成功 print(f发送分组 {seq}) return True def receive_ack(ack): 模拟接收 ACK返回确认序号 print(f收到 ACK {ack}) return ack # 发送窗口内的分组 while BASE TOTAL: # 窗口未满时继续发送 while NEXT_SEQ BASE WINDOW_SIZE and NEXT_SEQ TOTAL: send_packet(NEXT_SEQ) NEXT_SEQ 1 # 模拟收到累积确认 ack receive_ack(BASE 1) if ack BASE: BASE ack # 窗口向前滑动 else: # 超时重传所有未确认分组 print(f超时重传 {BASE} 到 {NEXT_SEQ-1}) for seq in range(BASE, NEXT_SEQ): send_packet(seq)这段代码的逻辑说明BASE是窗口基序号NEXT_SEQ是下一个待发送序号窗口大小固定为 4。发送方在窗口未满时持续发送收到累积确认后窗口向前滑动。如果确认序号没有前进说明超时重传所有已发未确认的分组。参数WINDOW_SIZE可以调整改大能提高吞吐但增加重传代价改小则相反。4.4 流量控制和拥塞控制的区别资料里把流量控制和拥塞控制放在一起讲但两者的目标不同流量控制是接收方通过通告窗口限制发送方速率防止接收缓冲区溢出拥塞控制是发送方根据网络状况调整发送速率防止网络过载。接收窗口和拥塞窗口取最小值才是实际发送窗口。理解这一点就能明白为什么SO_RCVBUF设置过小会导致吞吐下降——接收窗口小了发送方被限制住了。5. 避坑与常见问题端口、TIME_WAIT 和状态异常的排查记录5.1 端口号范围与连接数上限的误区现象以为一台客户端机器最多只能建立 65535 个连接。 原因把端口号范围当成了连接数上限。资料里明确指出连接由五元组协议、源 IP、源端口、目标 IP、目标端口唯一标识端口是逻辑概念连接数取决于五元组的组合数。 解决如果要发起上百万连接需要提供多个目标端口每个端口承担 6 万多个客户端连接。同时注意文件句柄限制每个 Socket 连接占用一个文件句柄。5.2 TIME_WAIT 堆积导致端口耗尽现象服务端主动关闭大量短连接后TIME_WAIT状态连接堆积新连接无法绑定端口。 原因主动关闭方进入TIME_WAIT后持续 2MSL期间该四元组不能被复用。 解决调整net.ipv4.tcp_tw_reuse允许复用TIME_WAIT状态的端口或让客户端主动关闭连接把TIME_WAIT转移到客户端侧。但资料里也提醒TIME_WAIT的存在是为了保证可靠终止和旧分节消逝不要盲目缩短。5.3 CLOSE_WAIT 堆积是代码问题现象服务端大量CLOSE_WAIT内存和句柄持续上涨。 原因对端发了 FIN本端回了 ACK但应用层没有调用close()连接一直停留在CLOSE_WAIT。 解决检查代码中是否有未关闭的 Socket、连接池是否泄漏、异常分支是否遗漏了close()。这是代码 bug不是内核参数能解决的。5.4 快速重传误判为丢包现象抓包看到发送方连续收到 3 个重复 ACK 后立即重传但接收方其实收到了数据。 原因网络乱序导致接收方收到不按序的分组触发重复 ACK。 解决快速重传本身就是为了应对乱序重传后如果接收方确认了所有数据说明只是乱序而非丢包。如果频繁触发检查网络路径是否存在多路径或拥塞。5.5 SO_RCVBUF 设置过小导致吞吐下降现象TCP 传输大文件时吞吐远低于带宽上限。 原因SO_RCVBUF设置过小接收窗口受限发送方被流量控制限制。 解决根据带宽时延积BDP计算合适的缓冲区大小公式为带宽 × RTT。例如 100Mbps 带宽、100ms RTTBDP 约为 1.25MB接收缓冲区至少应设置为这个量级。6. 进阶技巧用 tcpdump 和 ss 验证 TCP 状态迁移与重传行为理论看再多不如自己抓一次包。下面这套组合拳是我排查 TCP 问题的固定流程分享给你。第一步用tcpdump抓取指定端口的 TCP 流量# 抓取 9999 端口的 TCP 包保存到文件 tcpdump -i lo -nn -s 0 tcp port 9999 -w tcp_test.pcap # 实时查看三次握手和四次挥手 tcpdump -i lo -nn -S tcp port 9999参数说明-i lo指定回环网卡-nn不解析 IP 和端口-s 0抓完整包-S显示绝对序列号。抓完后用 Wireshark 打开tcp_test.pcap能看到完整的 SYN、SYNACK、ACK、FIN、ACK 序列。第二步用ss观察状态迁移# 每秒刷新一次观察状态变化 watch -n 1 ss -tan | grep 9999第三步模拟丢包验证重传。用tc命令在回环网卡上注入丢包# 注入 10% 丢包率 sudo tc qdisc add dev lo root netem loss 10% # 测试完后删除规则 sudo tc qdisc del dev lo root netem执行后重新传输数据用tcpdump抓包就能看到超时重传或快速重传的分节。这个实验能让你直观感受到 RTO 的动态调整和重复 ACK 的触发条件。最后说一个我自己的习惯每次遇到 TCP 连接异常先ss -tan看状态分布再tcpdump抓包确认握手挥手是否完整最后对照状态机图定位是哪一步出了问题。这套流程走下来大部分连接问题都能在十分钟内定位到方向。从那以后我每次上线新的网络服务都强制走一遍状态检查和抓包验证再也没被CLOSE_WAIT堆积坑过。希望帮到你。本文还有配套的精品资源点击获取
返回列表