当前位置: 首页 > news >正文

计算机网络(一)——TCP

1. TCP 的三个核心特性

TCP 是面向连接可靠传输基于字节流的协议。

  • 面向连接:通信双方必须先建立连接(虚拟的全双工信道),才能收发数据。
  • 可靠传输:通过序列号(Seq)、确认应答(ACK)、超时重传、流量控制和拥塞控制来保证数据不丢、不重、不乱序。
  • 基于字节流:TCP 把应用层数据当作一个连续的字节序列,分段封装成报文段传输,不关心消息边界。这意味着应用层要自己处理粘包/拆包问题(比如 Netty 的 LengthFieldBasedFrameDecoder )。

一个 TCP 连接在系统中由四元组唯一标识:

【源 IP, 源端口, 目的 IP, 目的端口】

内核会为每个连接维护一套状态信息,包括本端/对端序列号、发送/接收缓冲区、窗口大小等。

2. 三次握手

三次握手是 TCP 建立连接的过程:

  1. 第一次握手:客户端发送 SYN 报文(SYN=1,Seq=x),请求建立连接。
  2. 第二次握手:服务端收到 SYN,回复 SYN+ACK 报文(SYN=1,ACK=1,Ack=x+1,Seq=y),表示同意并同步序列号。
  3. 第三次握手:客户端收到 SYN+ACK,回复 ACK 报文(ACK=1,Ack=y+1,Seq=x+1),连接建立。
    在这里插入图片描述

为什么不是两次?
核心原因有三个:

  1. 防止历史连接干扰
    如果一个延迟很久的旧 SYN 报文到达服务端,服务端建立了连接,而客户端早已关闭,会导致“幽灵连接”。第三次握手能让客户端确认对端的响应是否是自己期望的。

  2. 确保双方序列号同步
    TCP 使用序列号来确认和重排数据包。三次握手可以保证双方初始序列号(ISN)都被确认,避免因序列号不同步导致数据错乱。

  3. 避免资源浪费
    如果没有第三步,服务端无法确认客户端是否收到 SYN+ACK。ACK 丢失时,服务端会一直等待,造成“半开连接”占满资源。

Linux 内核细节

  • ISN 生成方式:基于一个随时间递增的计数器 + 源/目的 IP + 端口等进行哈希,保证不可预测性(防止 TCP 序列号攻击)。
  • 重试策略:第一次握手丢失,客户端会按指数退避(1s、2s、4s…)重发 SYN,次数由 tcp_syn_retries 控制。
  • SYN 攻击防御:通过增大半连接队列(somaxconn)、开启 SYN Cookies(tcp_syncookies=1)、减少 SYN+ACK
    重传次数(tcp_synack_retries)等手段缓解。

3. 四次挥手:优雅断开连接

断开连接的四次挥手流程是这样的:

  1. 第一次挥手:主动关闭方(假设是客户端)发送 FIN 报文,表示没有数据要发了。
  2. 第二次挥手:服务端收到 FIN,返回 ACK,进入 CLOSE_WAIT 状态。这时服务端可能还有数据要发送。
  3. 第三次挥手:服务端发送 FIN 报文,表示自己也发完了。
  4. 第四次挥手:客户端返回 ACK,进入 TIME_WAIT 状态,等待 2MSL 后释放连接。

为什么需要四次?
因为 TCP 是全双工的,关闭连接需要双方分别关闭发送方向。FIN 只能单向关闭,所以需要两对 FIN+ACK。

TIME_WAIT 的意义

  • 确保最后的 ACK 能被对端收到(ACK 丢失时,对端会重发 FIN)。
  • 等待网络中可能残留的旧数据包消失,避免下一个连接收到脏数据。

Linux 内核细节

  • 默认 TIME_WAIT 持续 60s(tcp_fin_timeout 可调)。
  • 高并发短连接下,TIME_WAIT 会占用大量端口,可通过 tcp_tw_reuse(复用 TIME_WAIT 连接)和 tcp_tw_recycle(已废弃)优化。

4. 数据传输中的细节

TCP 在传输阶段依赖几个关键机制:

  1. 滑动窗口(Flow Control):接收方通过 Window Size 告诉发送方自己还能接收多少数据,防止溢出。
  2. 拥塞控制(Congestion Control):经典算法包括慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)、快速恢复(Fast Recovery)。Linux 现在常用 CUBIC。
  3. 超时重传(RTO):根据 RTT(往返时延)动态计算。
  4. 延迟确认(Delayed ACK):减少 ACK 数量,但可能影响实时性。
  5. Nagle 算法:合并小包,减少包数量,但会增加延迟(Netty、游戏开发常关闭)。

5. 工程实践与常见坑

  • HTTP Keep-Alive:复用 TCP 连接,减少三次握手开销,但要注意服务器连接数限制。
  • 短连接高并发:TIME_WAIT 爆炸时,优化内核参数或使用连接池。
  • 半关闭连接:MySQL Binlog dump 是典型场景,客户端发送完请求,保持接收端开启。
  • 防御 SYN Flood:云厂商的负载均衡会在内核前就拦截,但自己写 TCP 服务要考虑 SYN Cookies。
http://www.lryc.cn/news/617293.html

相关文章:

  • Vue脚手架模式与环境变量
  • 变频器实习DAY26 CDN 测试中心使用方法
  • Android16新特性速记
  • C语言如何安全的进行字符串拷贝
  • 从 GPT-2 到 gpt-oss:架构进步分析
  • 北京JAVA基础面试30天打卡07
  • Nacos-1--什么是Nacos?
  • 5G NR 非地面网络 (NTN)
  • JVM运维
  • C#(vs2015)利用unity实现弯管机仿真
  • 5G 非地面网络(NTN)最专业的方案
  • CSS accent-color:一键定制表单元素的主题色,告别样式冗余
  • 第2节 大模型分布式推理架构设计原则
  • XX生产线MES系统具体实施方案
  • 【Node.js从 0 到 1:入门实战与项目驱动】1.4 Node.js 的发展与生态(历史版本、LTS 版本、npm 生态系统)
  • CobaltStrike的搭建与使用
  • java基础概念(二)----变量(附练习题)
  • 【代码随想录day 17】 力扣 617.合并二叉树
  • 零外围双Buck 2C和2C1A!功率分配So Easy
  • Jmeter使用第二节-接口测试(Mac版)
  • MyBatis执行器与ORM特性深度解析
  • n8n中调用playwright-mcp 项目
  • ansible学习第一天
  • 定义短的魔术数字时小心负数的整型提升
  • Mybatis @Param参数传递说明
  • 三种常见的菜单路由封装方式详解
  • 邬贺铨院士:AI与数字安全融合是数字化建设核心驱动力
  • 算法73. 矩阵置零
  • Dubbo从入门到实战:分布式服务开发指南
  • React18 Transition特性详解