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

计算机网络---传输控制协议Transmission Control Protocol(TCP)

一、TCP的定位与核心特性

TCP(Transmission Control Protocol,传输控制协议)是TCP/IP协议栈中传输层的核心协议,与UDP(用户数据报协议)共同承担端到端数据传输功能。其设计目标是在不可靠的IP网络上提供可靠、有序、面向连接的字节流服务,是互联网中绝大多数应用(如HTTP、FTP、SMTP等)的基础。

与UDP相比,TCP的核心特性差异如下:

  • 面向连接:通信前需通过“三次握手”建立连接,结束后需“四次挥手”释放连接;UDP无连接。
  • 可靠传输:通过序号、确认、重传等机制确保数据不丢失、不重复、按序到达;UDP不保证可靠性。
  • 字节流服务:将应用层数据视为连续字节流,无消息边界;UDP保留消息边界。
  • 流量控制与拥塞控制:通过滑动窗口避免接收方缓冲区溢出,通过拥塞算法避免网络拥塞;UDP无此类机制。
  • 适用于场景:对可靠性要求高(如文件传输、网页加载);UDP适用于实时性要求高(如视频通话、游戏)。
二、TCP报文结构

TCP报文由首部数据两部分组成,首部最小20字节,最大60字节(含选项字段)。各字段含义如下:

字段长度(字节)含义
源端口/目的端口2/2标识发送端和接收端的应用进程(如HTTP默认80端口)。
序号(Sequence Number)4本报文数据段第一个字节的序号(用于按序重组和去重)。
确认号(Acknowledgment Number)4期望接收的下一字节序号(仅当ACK=1时有效,即确认已收到序号≤(确认号-1)的数据)。
数据偏移(Header Length)4位表示TCP首部长度(以32位字为单位,最小值5(20字节),最大值15(60字节))。
保留位6位预留未来使用,目前需设为0。
控制位(Flags)6位共6个标志位:URG(紧急指针有效)、ACK(确认号有效)、PSH(推数据至应用层)、RST(重置连接)、SYN(同步序号,建立连接)、FIN(终止连接)。
窗口大小(Window)2字节接收窗口(rwnd),告知发送方可接收的字节数(流量控制核心字段)。
校验和(Checksum)2字节用于检测报文段在传输中是否损坏(覆盖伪首部、TCP首部、数据)。
紧急指针(Urgent Pointer)2字节当URG=1时有效,指示紧急数据在报文段中的偏移量(紧急数据优先处理)。
选项(Options)0-40字节可选字段,如MSS(最大报文段长度)、SACK(选择确认)、Window Scale(窗口扩大因子)等。
三、TCP连接管理

TCP是“面向连接”的协议,连接管理包含建立连接(三次握手)释放连接(四次挥手) 两个过程,通过控制位(SYN、ACK、FIN)实现。

1. 三次握手(建立连接)

三次握手的目标是:① 确保双方收发能力正常;② 协商初始序号(ISN);③ 同步连接状态。流程如下:

  • 第一次握手:客户端 → 服务器
    发送SYN报文(SYN=1,ACK=0),携带客户端初始序号ISN_c(如x)。此时客户端进入SYN_SENT状态。

  • 第二次握手:服务器 → 客户端
    服务器收到SYN后,回复SYN+ACK报文(SYN=1,ACK=1),携带服务器初始序号ISN_s(如y),并确认客户端序号(确认号=ISN_c+1=x+1)。此时服务器进入SYN_RCVD状态。

  • 第三次握手:客户端 → 服务器
    客户端收到SYN+ACK后,发送ACK报文(ACK=1),确认服务器序号(确认号=ISN_s+1=y+1)。此时客户端进入ESTABLISHED状态;服务器收到ACK后也进入ESTABLISHED状态,连接建立。

在这里插入图片描述

为何需要三次握手?

  • 防止“过期连接请求”干扰:若客户端的SYN报文因网络延迟到达服务器,服务器会误以为是新连接并回复SYN+ACK。若仅两次握手,服务器会直接建立连接并等待数据,但客户端已丢弃该过期请求,导致服务器资源浪费。三次握手通过客户端的最终ACK,确保双方确认“当前连接有效”。

用最简单的例子解释为什么需要三次握手:
A: 喂,能听见吗?
B: 能听见,你能听见我吗?
A: 能听见。

在这里插入图片描述

2. 四次挥手(释放连接)

TCP支持“半关闭”(一方关闭发送后仍可接收数据),因此释放连接需四次交互:

  • 第一次挥手:客户端 → 服务器
    客户端主动关闭,发送FIN报文(FIN=1,ACK=1),表示不再发送数据(但可接收),携带序号u(最后发送字节的序号+1)。客户端进入FIN_WAIT_1状态。

  • 第二次挥手:服务器 → 客户端
    服务器收到FIN后,回复ACK报文(ACK=1),确认号=u+1,告知客户端“已收到关闭请求”。服务器进入CLOSE_WAIT状态,客户端进入FIN_WAIT_2状态(等待服务器剩余数据)。

  • 第三次挥手:服务器 → 客户端
    服务器发送完剩余数据后,发送FIN报文(FIN=1,ACK=1),携带序号v(服务器最后发送字节的序号+1),确认号=u+1(与第二次挥手一致)。服务器进入LAST_ACK状态。

  • 第四次挥手:客户端 → 服务器
    客户端收到FIN后,回复ACK报文(ACK=1),确认号=v+1,客户端进入TIME_WAIT状态;服务器收到ACK后进入CLOSED状态。客户端等待2MSL(最大报文段寿命,通常为1-2分钟)后,也进入CLOSED状态,释放连接。

在这里插入图片描述

四次挥手:
A:再见
B:收到
B:再见
A:收到

关键细节

  • 为何四次挥手? 第二次挥手(ACK)和第三次挥手(FIN)无法合并,因为服务器可能还有数据需发送(半关闭状态)。
  • TIME_WAIT状态:持续2MSL(确保最后一个ACK被服务器收到;防止旧报文干扰新连接)。若服务器未收到ACK,会重发FIN,客户端需在TIME_WAIT内处理。
3. TCP状态机

连接管理的状态转换可通过状态机描述,核心状态包括:

  • 客户端:CLOSEDSYN_SENTESTABLISHEDFIN_WAIT_1FIN_WAIT_2TIME_WAITCLOSED
  • 服务器:CLOSEDLISTENSYN_RCVDESTABLISHEDCLOSE_WAITLAST_ACKCLOSED

异常状态:RST(重置连接,用于处理错误,如连接不存在时强制关闭)。

四、TCP可靠传输机制

TCP通过多重机制确保数据“可靠传输”(不丢失、不重复、按序到达),核心包括序号与确认超时重传快速重传与恢复选择确认(SACK) 等。

1. 序号与确认机制
  • 序号:每个字节数据分配唯一序号(初始为ISN,后续按字节递增)。例如,若ISN=100,发送50字节数据,序号为100-149,下一个序号为150。
  • 确认号:采用“累计确认”,表示“已正确接收序号≤(确认号-1)的所有数据”,期望接收确认号对应的字节。例如,收到序号100-149的数据,确认号为150。
2. 超时重传

当发送方未在规定时间内收到确认,会重传该数据,关键是超时时间(RTO) 的计算:

  • RTO需动态调整(基于RTT,往返时间):
    • 样本RTT(SampleRTT):单次报文往返时间;
    • 平滑RTT(SRTT):SRTT = (1-α)×SRTT + α×SampleRTT(α通常为0.125);
    • RTT偏差(RTTVAR):RTTVAR = (1-β)×RTTVAR + β×|SampleRTT - SRTT|(β通常为0.25);
    • 最终RTO = SRTT + 4×RTTVAR(确保97%的RTT落在RTO内)。
3. 快速重传与快速恢复
  • 快速重传:当发送方收到3个重复确认(确认号相同),无需等待超时,立即重传未被确认的报文(推断该报文已丢失)。
  • 快速恢复:重传后不执行慢启动(避免网络拥塞加剧),而是将拥塞窗口(cwnd)设为慢启动阈值(ssthresh),直接进入拥塞避免阶段。
4. 选择确认(SACK)

累计确认的缺陷:若中间报文丢失,后续报文即使到达也无法被单独确认。SACK通过选项字段告知发送方“已接收的非连续数据块”,发送方仅重传丢失部分。例如,接收方收到1-100、201-300,SACK会标记这两个区间,发送方仅重传101-200。

五、流量控制

流量控制用于防止发送方速率超过接收方处理能力,基于“滑动窗口机制”,通过接收窗口(rwnd)实现。

1. 滑动窗口原理
  • 发送窗口:发送方可发送但未确认的数据范围,大小由接收窗口(rwnd)和拥塞窗口(cwnd)共同决定(发送窗口=min(rwnd, cwnd))。
  • 接收窗口:接收方缓冲区剩余空间(rwnd = 接收缓冲区大小 - 已接收未读取数据量),通过TCP报文的“窗口大小”字段告知发送方。

窗口分为三部分:

  • 已发送且确认:序号≤已确认序号;
  • 已发送未确认:序号在已确认序号+1 至 发送窗口左沿-1;
  • 未发送但可发送:序号在发送窗口左沿 至 发送窗口右沿-1;
  • 不可发送:序号≥发送窗口右沿。
2. 窗口动态调整
  • 接收方随缓冲区使用情况更新rwnd(若缓冲区满,rwnd=0);
  • 发送方根据rwnd调整发送窗口:若rwnd=0,发送方停止发送,定期发送“零窗口探测报文”(1字节),接收方回复新的rwnd后恢复发送。
六、拥塞控制

拥塞控制用于防止发送方速率超过网络承载能力(避免网络拥塞导致丢包),核心是通过调整拥塞窗口(cwnd) 控制发送速率,涉及四大算法:慢启动、拥塞避免、快重传、快恢复。

1. 核心参数
  • 拥塞窗口(cwnd):发送方根据网络拥塞状态动态调整的窗口(初始为1MSS);
  • 慢启动阈值(ssthresh):cwnd增长的临界点(初始为较大值,如65535字节)。
2. 算法流程
  • 慢启动:cwnd从1MSS开始,每收到一个确认(或每经过一个RTT),cwnd翻倍(指数增长),直到cwnd达到ssthresh,进入拥塞避免阶段。
  • 拥塞避免:cwnd每经过一个RTT增加1MSS(线性增长),降低拥塞风险。
  • 拥塞处理
    • 若超时重传(严重拥塞):ssthresh = cwnd/2,cwnd重置为1MSS,重新慢启动;
    • 若收到3个重复确认(轻度拥塞):触发快重传,ssthresh = cwnd/2,cwnd = ssthresh,进入拥塞避免(快恢复)。
七、其他重要特性
  1. 面向字节流:TCP将应用数据视为连续字节流,无消息边界,应用层需自行处理数据分割(如通过长度字段或分隔符)。
  2. 最大报文段长度(MSS):TCP报文段最大数据部分长度(MSS = MTU - IP首部长度 - TCP首部长度,以太网中通常为1460字节),在三次握手的SYN报文中协商。
  3. Nagle算法:减少小报文数量(如连续发送多个1字节数据),规则是:未确认数据时,仅当数据达MSS或收到确认,才发送。可通过TCP_NODELAY选项关闭(适用于实时性场景,如SSH)。
  4. 延迟确认:接收方不立即回复ACK,而是延迟500ms(或在发送数据时一并确认),减少ACK数量。若500ms内收到新数据,会合并确认。
八、常见问题与优化
  1. 粘包问题:TCP字节流无边界,导致应用层收到的数据可能合并(粘包)或拆分。解决方法:

    • 固定长度:每个消息固定大小;
    • 分隔符:用特殊字符(如\r\n)分隔消息;
    • 长度前缀:消息头部包含长度字段。
  2. TIME_WAIT积累:高并发场景下,大量TIME_WAIT状态连接会占用端口。优化方案:

    • 开启SO_REUSEADDR:允许端口快速复用;
    • 缩短TIME_WAIT时长(如调整net.ipv4.tcp_fin_timeout)。
  3. 拥塞控制优化:传统算法(如Reno)在高带宽延迟网络(如卫星链路)效率低,现代算法如BBR(基于带宽和延迟)、CUBIC(基于三次函数增长)可提升性能。


TCP是互联网可靠传输的基石,通过三次握手建立连接、四次挥手释放连接,结合序号确认、超时重传、SACK等机制确保可靠性,通过滑动窗口实现流量控制,通过慢启动、拥塞避免等算法实现拥塞控制。理解TCP的核心机制,对网络编程、性能优化及问题排查至关重要。其设计兼顾了可靠性与效率,是计算机网络中最复杂且应用最广泛的协议之一。

http://www.dtcms.com/a/331381.html

相关文章:

  • Redis的 ​​散列(Hash)​​ 和 ​​列表(List)​​ 数据结构操作详解
  • 力扣-64.最小路径和
  • 【AI推理部署教程】使用 vLLM 运行智谱 GLM-4.5V 视觉语言模型推理服务
  • 电商双 11 美妆数据分析总结(补充)
  • 入门概述(面试常问)
  • 中久数创——笔试题
  • Android构建工具版本兼容性对照表
  • Git 中切换到指定 tag
  • 会议系统核心流程详解:创建、加入与消息交互
  • 卫星通信链路预算之七:上行载噪比计算
  • MySQL-dble分库分表方案
  • 【最新版】怎么下载mysqlclient并成功安装?
  • 物化视图优先迁移大表,缩短逻辑迁移时间
  • MySql——binlog和redolog的区别
  • uniapp开发动态添加密码验证
  • Go语言全面解析:从入门到精通
  • C/C++ 指针与内存操作详解——从一级指针到字符串转换函数的完整解析
  • 拒绝“孤岛式”作战,全方位构筑隧道应急通信解决方案
  • Java 学习笔记(基础篇2)
  • 13、C 语言结构体尺寸知识点总结
  • LeetCode 刷题【41. 缺失的第一个正数】
  • 【力扣322】零钱兑换
  • 非容器方式安装Prometheus和Grafana,以及nginx配置访问Grafana
  • GraphRAG查询(Query)流程实现原理分析
  • NetLimiter:精准掌控网络流量,优化网络体验
  • 《中国人工智能安全承诺框架》发布
  • arthas火焰图怎么看
  • 搭建 Docker 私有仓库
  • 前端css学习笔记5:列表表格背景样式设置
  • 【Golang】Golang内存泄漏问题排查(二)