LabHub
学习 学习路径 课程

网络基础

TCP — 连接与可靠性是怎么造出来的

在 LabHub 中继续学习

一句话总结

TCP 通过序列号、确认、重传和两种窗口,营造“既不丢失也不乱序的字节流”这一抽象。

概念图: 建立连接。 · 关闭连接。 · TIME-WAIT · 可靠性。

为什么需要它

IP 只尽力而为,不作任何承诺。数据包可能丢失、乱序或重复,而多数应用都假设“按发送顺序接收”。TCP 用来弥合这一差距。

工作原理

建立连接。 客户端发送 SYN,服务器回复 SYN-ACK,客户端再发送 ACK。之所以需要三次交换,是因为双方都要向对方公布并确认自己的初始序列号。

关闭连接。 两个方向分别关闭,因此 FIN 和 ACK 各出现两次,共四次交换。主动关闭方会保持 TIME-WAIT 状态 2MSL(最大报文段寿命的两倍),防止迟到报文污染复用同一端口对的新连接,并在最后一个 ACK 丢失时能够重发。高负载服务器存在数万个 TIME-WAIT 套接字很正常,为消除它们而随意修改内核参数反而会引发问题。

可靠性。 接收方用 ACK 告知连续收到的位置。发送方在一定时间(RTO)内未获确认就重传;同一个 ACK 重复三次时,不等超时便立即重传(快速重传)。

两个窗口。 流量控制通过接收方公布的接收窗口(rwnd)表示“我只能接收这么多”;拥塞控制通过发送方维护的拥塞窗口(cwnd)估计“网络只能承受这么多”。两者目的不同。 实际发送量受较小者限制。拥塞窗口在慢启动阶段指数增长,超过阈值后线性增长,检测到丢包后大幅缩小(AIMD)。

实际工作中的表现

两种连接失败消息的区别决定了诊断方向。

Connection refused 表示对方返回了 RST。 这证明数据包已到达目的地并返回,路由、安全组和网络策略均已通过。问题在目标主机内部:进程已退出、监听了其他端口、没有绑定 0.0.0.0 而是只绑定 127.0.0.1,或负载均衡器后没有健康后端。“出现 refused 所以是防火墙”通常是错的。 实际防火墙多采用静默丢弃(DROP),无响应会表现为 timeout。

Connection timed out 表示 SYN 重传耗尽仍无响应。 Linux 默认重传 tcp_syn_retries 次,间隔逐次翻倍。1+2+4+8+16+32+64 合计 127 秒。若应用配置超时为 30 秒,却实际 127 秒才失败,说明该配置并未生效。

即使存在监听器也可能 timeout。accept 队列已满时,内核会静默丢弃新 SYN。用 ss -ltn 查看监听套接字时,Recv-Q 是当前队列长度,Send-Q 是上限。若 Recv-Q 已逼近或超过 Send-Q,原因是应用吞吐量而不是网络。

后续测验将确认什么

确认你能解释 refused 与 timeout 分别对应怎样的数据包交换,以及流量控制与拥塞控制有何不同。