计算机网络——TCP 协议原理总结
目录
- 1.网络是不可靠的
- 2.TCP 概念和特点
- 3.可靠传输机制
- 1.一问一答的方式
- 2.流水线传输的方式
- 1.回退 N 重传
- 2.选择重传
- 4.TCP 滑动窗口机制
- 数据包序号
- 确认号和累计确认
- 发送机制
- 发送窗口
- 接收窗口
- 窗口大小
- 5.TCP的建立和释放
- 1.建立连接-三次握手
- 三次握手的必要性
- 1.三次握手是为了确定双方的收发能力
- 2.序号同步的确定性
- 3.历史失效连接请求的乱序问题
- 4.三次握手中丢包的情况
- 5.数据传输的开始时机
- 6.连接关闭 - 四次挥手
- 7.挥手四次的必要性
- 8.等待 2MSL 时间的原因
- 6.TCP协议头
- 7.概念知识总览
1.网络是不可靠的
计算机网络是不可靠的,存在 丢包、乱序、延时 。
这是众多 TCP 协议机制的设计出发点,万恶之源,将贯穿全文。
2.TCP 概念和特点
TCP 协议全称 传输控制协议
, 是一种 面向连接的、可靠的、面向字节流的 传输层通信协议。
TCP 在 TCP/IP 协议模型
中位于传输层。
TCP/IP 模型中各层数据包结构的关系如下图。
TCP 协议的主要特点:
- 面向连接,一对一通信。
- 可靠交付:保序、不重复、不丢失。
- 全双工通信:双方均可收发。
- 和上层应用进程的交互方式是 面向字节流的。
TCP 和上层应用进程的交互方式:
- 发送方可以发送不同大小的数据块到发送缓存。
- 先会对发送缓存内的数据分段,打包成 TCP 数据包再发送。
- 在接收一侧,数据包会先进入接收缓存区。
- 当一定数量的数据包全部到达,重排、组装,以数据流方式吐给接收方。
虽然 TCP 是面向字节流的,但是 TCP 所处理的数据单元却是面向报文段的, 也就是本文所说的数据包。
将看到,短短 可靠交付 四字背后并不简单。
3.可靠传输机制
若不止考虑 TCP 协议本身的实现,如何设计可靠的网络通信?
首先,由于 丢包的可能性,要实现可靠通信:
- 发送方要知道对方接收成功,因此需要接收方回复确认 即 ACK。
- 如果丢包发生,发送方需要重传。
一种触发重传的方式是,超时重传 (也有其他触发方法,见后续 TCP 重传机制 )。
网络延时发生时,重传可能会导致重复:
- 接收方会丢弃收到的重复数据包,但是仍然回复确认。
- 发送方会丢弃收到的重复确认包。
其次,对于如何发送确认包和重传包,有两种方式。
1.一问一答的方式
也叫做 停止并等待 ARQ 协议, 是指 发送方等到接收方的确认包后,再发下一个数据包 。
类似乒乓方式,具体来说:
- 如果时限内收到对方确认,才发送下一个数据包。
- 否则,重传当前数据包。
可以看到这种方式下,发送方大部分时间在等待,效率非常低。
2.流水线传输的方式
叫做 连续 ARQ 协议 , 是指 发送方会连续发送一组数据包,同时等待这些数据包的确认 。
具体来说:
- 发送方发送一批数据包。
- 同步地接收对方的确认包。
简单来说, 发送方不闲着,一边发送,一边等回复 。
可以看到这种方式相对一问一答的方式,效率要高。
如果发生丢包或延时,需要重传,有两种方式:
1.回退 N 重传
发送方每发送一个数据包,都会发起一个定时器。
一旦一个某个定时器触发,就会重传。
发送指针回退到未拿到确认的数据包处,以实现重传。
可以看到,此方法下, 会重传后面所有的数据包。
2.选择重传
同样,每发送一个数据包,都会发起一个定时器。
不同点仅在于, 只重传未拿到确认的数据包,不回退发送指针。
综合以上,得出的结论是,不考虑 TCP 协议的具体实现的话, 要实现可靠的网络通信,需要依赖确认和重传机制, 并且一个好的办法是采用流水线传输的方式。
而流水线传输方式,正是下一个部分 TCP 协议中的 滑动窗口机制 的引子。
4.TCP 滑动窗口机制
滑动窗口机制是 TCP 协议的精髓所在,它是 TCP 协议设计的基本框架 。
滑动窗口机制就是 流水线传输方式 在 TCP 协议中的细化设计, 发送方一边连续地发送数据包,一边等待接收方的确认。
滑动窗口分为两种:发送窗口 和 接收窗口。
由于 TCP 是全双工的, 所以通信的每一端都会同时维护两种窗口 。
数据包序号
在 可靠传输的基础机制 中, 接收的数据包可能是重复的、乱序的,因此 TCP 会对每一个数据包进行唯一标号, 叫做数据包的序号。
数据包的序号是 TCP 协议头
中的一个 32 比特大小的整数字段。
每次发送一个包,这个序号就会增加一。
TCP 是全双工的,两个通信端各自维护自己的序号。
因为 网络延时不可控, 如果两次连接建立时差很短、或者连接重建后老连接的数据包延迟到达, 会造成序号冲突。
所以,序号并非由固定数字初始化。可以综合时间、随机数来生成等。
确认号和累计确认
在 TCP 中,一个用以确认的回复包,会有确认号。
如果一个数据包同时也是一个确认包,那么它也会有确认号。
一个序号为 SEQ 的数据包,其确认包的确认号会是 SEQ+1 。
同样,确认号也是 TCP 协议头
中的一个 32 比特大小的整数字段。
可以理解为,接收方已收到序号为 SEQ 的数据包,期待发送方下一次给 SEQ+1 的包。
更广义的理解是, 确认号是接收方期望对方发送的下一个包的序号 。
下图中,发送方连续发送一组包,如果中间有丢包, 接收方则期待序号最小的丢失的包。当重传成功后, 接收方仍然期待下一个未拿到的数据包:
接收方所期待的是序号最小的没拿到的数据包 。
这种确认号的机制,即可实现累计确认机制:
接收方确认了标号为 SEQ 的数据包, 即代表确认了所有小于 SEQ 的数据包, 此时接收方给的确认号是 SEQ+1 。
累计确认其实是一种批量确认的机制,以减少确认包的数量。
此外,如果接收方恰好需要发送数据,确认号可以直接标在数据包上,即捎带确认。
一个问题是,如何控制累计确认的时机?
TCP 协议中的 Nagle
算法 给出的办法是 延迟确认。
其大概的原理是,未确认的包达到一定量、或者达到一个时间阈值,才回复一次确认。
所以说, 在默认的 TCP 协议中,确认不是立即回复的,而是延迟的 。
不过,接收方的延迟确认不应该过分延迟,否则会造成发送方的重传,浪费网络资源。
可以设置 TCP_NODELAY
选项 来禁用 Nagle 算法。
TCP 的累计确认机制,是累计确认和延迟确认两个策略的综合。
此外,TCP 协议还有另外一种确认机制,叫做 选择确认机制 ,将会后面讲到。
发送机制
已经讲过,TCP 协议默认的 Nagle
算法 采用了延迟确认的方法。
对应的,发送的时机如何确定?
办法是类似的,大概是,未发送的包达到一定量、或者达到一个时间阈值,才发送一次。
TCP 的发送机制,是累计发送和延迟发送两个策略的综合。
同样可以设置 TCP_NODELAY
选项 来关闭延迟发送的行为。
发送窗口
发送窗口的示意图如下,当收到对方的累计确认后,则向右滑动。
注意的是 窗口大小 是有限的(稍后将讨论它的受限情况), 发送方只能发送窗口内的数据包 。
接收窗口
接收窗口的示意图如下,当回复对方确认后,则向右滑动。
仍需注意 窗口大小 是有限的(稍后将讨论它的受限情况), 接收方只能接收窗口内的数据包 。
由于 网络数据包是乱序的 , 所以接收后的数据包会按照序号重新排序,才可以交付给应用程序。
窗口大小
窗口的大小是受限的,也是动态的 。
窗口大小是 TCP 协议头
中的一个 16 比特大小的整数字段。
首先,显然 接收窗口受限于接收缓存区的大小, 发送窗口受限于发送缓存区的大小 。
其次指出, 发送窗口大小也受限于接收窗口大小 。
这其实比较容易理解,发送方是生产者,接收方是消费者, 如果生产速度快而消费速度慢,则会导致接收方来不及接收。
所以,发送方只能发送窗口内的数据包 。
其实,这就是 流量控制机制 : 由接收方控制的、调节发送方生产速度的机制 , 其具体的实现方式,就是在回复时设置 TCP 协议头
中的窗口大小字段。
窗口的大小也是动态变化的, 因为两端接收和发送能力是动态变化的 :
- 接收能力的变化导致窗口大小的变化,即后面所讲的 TCP 流量控制机制。
- 发送能力的变化导致窗口大小的变化,即后面所讲的 TCP 拥塞控制机制。
可以看到,滑动窗口的大小是一个贯穿式的重要概念。
但是,如果窗口要缩小,窗口的前沿是不可以向前收缩的。
窗口收缩的方法则是,慢慢地,随着已发送的数据包得到确认, 保持窗口前沿不动,前移窗口后沿。
因此, 发送窗口也并不总和接收窗口一样大 。
窗口大小的初始化,是在 连接建立 过程中两端协商确定的, 在后续的传输阶段,它会因主动或被动的原因而动态变化。
5.TCP的建立和释放
1.建立连接-三次握手
首先,TCP 连接建立过程要解决的问题:
- 确定双方都可以正常收发 TCP 数据包。
- 双方协商一些参数和可选项(例如前面所讲的 选择确认 、窗口大小 等), 尤其是交换初始序号。
- 对资源进行分配,比如缓存区、端口号。
下面是 TCP 协议三次握手建立连接的过程示意图,其中
- SYN(synchronous) 是同步标志位 ,表示开始传输数据的意思。
- ACK(acknowledgement) 是确认标志位,表示是否启用确认机制。
- ack(小写)是前面所说的 确认号。
- seq 是前面所说的 序号 。
具体过程的描述如下:
- 客户端发送一个 TCP 数据包,主动发起连接。
设置 SYN=1 标志位,表示发起连接,想要传输数据。
客户端初始化自己的数据包序号 seq=x ,一同发送给对方。
- 服务端收到对方的连接请求,回复对方确认包。
设置回复标志位 ACK=1 ,表示确认。
根据 确认号的规则, 同时设 ack=x+1 表示期待对方下一次发过来的数据包序号为 x+1。
因为 TCP 是全双工的,服务端也会设置 SYN=1 , 并初始化自己的数据包序号 seq=y ,捎带回复给客户端。
此时,服务端可以确定: 客户端可以发送 TCP 数据包,自身可以接收 TCP 数据包 。
- 客户端收到对方的确认包,并回复对方确认。
同样,设置回复标志位 ACK=1,表示确认。
对方的序号是 y , 回复对方 ack=y+1 表示期待对方下一次发来的数据包序号为 y+1 。
同时,自身的数据包序号需要自增 seq=x+1 。
自己发送上一个数据包,对方收到了,并且收到了对方回复。
所以客户端可以确定: 服务端可以正常收发 TCP 数据包, 自身也可以正常收发 TCP 数据包 。
- 服务端收到客户端的确认,三次握手结束。
此时服务端可以进一步确定:
客户端端可以正常接收 TCP 数据包, 自身也可以正常发送 TCP 数据包 。
三次握手结束后,双方都可以确定对方是可以正常收发 TCP 数据的。
三次握手的必要性
一个经常出现的问题是: 两次握手可以吗?
当然是不可以的,可以分几个方面解释:
1.三次握手是为了确定双方的收发能力
如果缺少最后一次 ACK 的话,服务端就无法知道客户端是否可以接收 TCP 数据, 也无法知道自己的发送是否成功,就无法做到可靠传输。
2.序号同步的确定性
如果缺少最后一次 ACK 的话,服务端就无法确定对方有无收到自己的初始序号。
前面讲到,数据包的序号是 TCP 滑动窗口机制的基本字段,它如果是不可靠的, 后续的确认机制、重传机制等都无从谈起。
网络是不可靠的,存在丢包,所以连接建立时, 双方都必须确定初始序号交到了对方手中。
三次握手过程,也是可靠地交换初始序号的过程 。
3.历史失效连接请求的乱序问题
网络中,数据传输可能存在延迟、乱序。
如果一个老的失效的连接请求,延迟到达服务端,倘若缺少第三次握手, 服务端会建立一条新连接,直接进入 ESTABLISHED 状态。
客户端收到服务端的回复包时,可以根据序号是否过期判断是否是失效连接。
在三次握手的情况下,客户端就进一步可以发送 RST 标志,终止连接。
如果不是历史失效连接,客户端则发送 ACK 标志,正常建立连接。
4.三次握手中丢包的情况
另一个常见的问题是: 如果第三次 ACK 丢包呢?
无论哪一次通信发生丢包或延迟,都出发 TCP 的 重传机制 。
简单说,再发一次,如果达到一定次数,则放弃连接。
对于第三次 ACK 丢包的情况,重试一定次数后,服务端会关闭连接,回收资源。
不过,服务端单方面关闭连接,客户端并不知晓,它认为连接已经建立。
如果客户端向服务端发送数据,会被服务端打回 RST 报文, 借此客户端可知道连接失效。
5.数据传输的开始时机
上面的 三次握手图示 中,一个细节是:
- 客户端在两次握手之后就进入了 ESTABLISHED 状态。
- 服务端则是在三次握手之后才进入 ESTABLISHED 状态。
其原因在于, 在 第二次握手 后, 客户端已经可以确定双方都可以正常收发数据包 。
所以,客户端可以提前进入 ESTABLISHED 状态,分配端口,开始通信。
因此, 第三次 ACK 是可以捎带客户端的数据一并发送的 。
服务端直到 第三次握手 成功之后,才可以确定双方都正常, 所以它会稍晚进入 ESTABLISHED。
6.连接关闭 - 四次挥手
TCP 的连接释放过程,需要注意两个点:
- TCP 是全双工的。
- 双方都可以主动释放连接。
释放连接的过程有一个重要的目的:
双方都要确定地知道对方不再发送数据了,连接才正式关闭 。
假设客户端主动关闭,下面是 TCP 协议四次挥手释放连接的过程示意图。
其中 FIN(finish)是结束数据传输的标志位。
具体过程的描述如下:
- 客户端发送 FIN 数据包,不再发送数据。
设置 FIN=1 标志位,表示想要关闭连接,不再发送数据。
但是,此时服务端还可以继续发送数据 。
- 服务端收到 FIN 数据包,回复确认 。
服务端对于 FIN 包也会进行确认。
此时服务端明确知道,客户端不再发送数据了 。
- 服务端传输完剩余数据 。
由于 TCP 是全双工的, 连接关闭由客户端主动发起,并不意味着服务端的数据已传输完。
- 服务端需要把剩余数据传输完毕。
此时服务端知道,双方都不再发送数据了。 。
服务端发送 FIN 数据包,不再发送数据包 。
同样,设置 FIN=1 标志位,表示服务端不再发送数据。
- 客户端收到对方 FIN 包后,回复确认 。
任何一方结束数据发送,都要确保对方是知道的,就需要对方确认。
此时客户端知道,双方都不再发送数据了。
- 客户端等待 2MSL 时间等待后,四次挥手结束,释放所有资源
再次明确, FIN 标志位的意思是,不再发送数据 。
7.挥手四次的必要性
双方都必须对 FIN 包做确认, 这样对方才可以确定地知道自己不再发送数据。
TCP 连接的建立需要三次握手,是因为, 第二次握手过程服务端将设置 SYN 和 ACK 合并为一个数据包发送,所以是三次 。
而对于释放连接的情况, 无法将第二次和第三次合并, 因为中间还要传输数据, 所以是四次。
如果任何一个确认包发生丢包或延迟,主动设置 FIN 的一方会触发重传。
8.等待 2MSL 时间的原因
首先,MSL 是指报文在网络中最大生存时间。
2MSL 就是两倍的 MSL ,也被叫做 TIME_WAIT 时间, 在 linux 中常被设置为 2*60s 。
2MSL 的值一定需要大于重传超时阈值 。
为何要等待这么长时间呢?
- 如果最后一次 ACK 丢包呢?
前面有说过,任何一方的 FIN 包丢失后,如果超时未收到对方确认, 就会触发重传。
如果客户端在一定时间内未收到服务端的 FIN 包重传,说明对方已经收到 ACK 。
否则,如果收到服务端的 FIN 包重传,自然回复 ACK。
一次 ACK 包的发送时间,再算上重传 FIN 的时间,所以叫做 2MSL 。
不过,无论如何,2MSL 时间至少要比重传超时阈值长。
2. 防止新老连接数据包混乱
如果立即释放端口资源,此端口可能被一个新连接立即使用。
如此的话,假设网络中存在老数据包的延迟,那么老数据包会被新连接接收,造成混乱。
所以, 等待一定时间,使得网络中潜在的、可能延迟传输的数据包悉数殆尽, 才不会影响到后面的连接。
综合来看,还是因为网络是不可靠的。
6.TCP协议头
7.概念知识总览
计算机网络——TCP 协议原理总结相关推荐
- 计算机网络——HTTP协议原理
摘要 在日常的开发中,很多开发的同学可能很少了解的HTTP协议的底层原理.HTTP协议的底层涉及到请求响应模型,HTTP的工作流程.cookie和session的原理等.本博文主要介绍计算机网络中HT ...
- 计算机网络-TCP协议
目录 1 概述 2 TCP的主要特点 3 TCP的连接 4 可靠传输的工作原理 4.1 停止等待协议 4.1.1 无差错情况 4.1.2 出现差错 4.2 自动重传请求ARQ 4.3 连续 ARQ 协 ...
- 计算机网络 TCP协议如何保证可靠传输
目录 TCP如何保证可靠传输 TCP以段为单位发送数据 重传机制 超时重传 重发超时如何确定 快速重传 SACK 的引入是为了解决什么问题? D-SACK 又是什么东西? ARQ协议 停止等待ARQ协 ...
- 计算机网络中TCP连接管理,计算机网络 TCP协议
TCP:面向连接的运输 TCP协议是面向连接的协议,把连接作为最基本的抽象.每一条TCP连接唯一的被通信两端的两个端点所确定.TCP协议是点对点,而不是点对多点.端点又被称为套接字,TCP协议规定,I ...
- 计算机网络——TCP 协议总结
文章目录 TCP 协议总结 1.主要特点 2.TCP 和 UDP 的区别 3.TCP 头部 4.三次握手--建立连接 5.四次挥手--释放连接 6.流量控制 7.拥塞控制 TCP 协议总结 1.主要特 ...
- 计算机网络—TCP协议
建议将思维导图保存下来观看,或点击这里在线观看
- 计算机网络——IP协议基础原理
摘要 IP协议提供的一种统一的地址格式.它为互联网上的每一个网络和主机分配一个逻辑地址所以IP地址也叫逻辑地址,用来屏蔽物理地址的差异,MAC地址每一个机器都有一个编码.IP地址是32位二进制数据分为 ...
- 计算机网络——ARP协议(地址解析)原理
摘要 地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议.主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的 ...
- 计算机网络——ARQ协议(自动重传请求)原理
摘要 自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层和传输层的错误纠正协议之一.它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输 ...
最新文章
- jquery gridly (拖拽插件)
- 王高利:awstats
- GHOST_XP详细制作过程
- 成功解决AttributeError: 'NoneType' object has no attribute '__array_interface__'
- 【攻防世界013】elrond32
- c++ map的使用方法[转]
- office 2003和office 2013同时安装使用的问题
- 研发管理(2)---七个工作法则
- 无法使用struts2注释_带有注释且没有struts.xml文件的Struts 2 Hello World示例
- java秒数格式转换_Java中整数(秒数)转换为时分秒格式(xx:xx:xx)
- Map 3D 2012定制和应用程序开发Webcast将于明天(6月23号)进行
- OpenCV : 投影变换
- url怎么隐藏html后缀,去除url后缀(.html,.jsp等)的有效方法
- 网站备案需要买服务器吗,域名备案需要购买服务器吗
- forge不能用java打开_我玩我的世界把java更新了以后,就再也进不了加了forge的版本了,启动器,游戏,forge都重...
- 2827: 千山鸟飞绝 非旋treap
- 在计算机硬盘使用前需要做的工作是,工作电脑的硬盘该如何保养
- Java 根据贷款年限对应的不同利率计算月供
- 苹果耳机AirPods Max(Pro)的空间音频技术,Unity端开源框架下载
- 让word文档中的代码更美观
热门文章
- mc启动器需要用的java_《我的世界》为啥需要启动器,而不是直接游戏?专业角度给你分析...
- 我的世界电脑版java路径_我的世界启动器Java路径怎么设置?java路径设置攻略
- 广义相对论基础【1】狭义相对论中的张量
- n行Python代码系列:四行程序实现两个视频同屏播放
- 统计信号处理基础 习题解答4-2
- 彻底弄懂python3中的回调函数
- linux下 远程桌面连接,Unix/Linux下通过远程桌面连接Windows OS
- TIFF World File (TFW)格式解析
- 应用笔记AN1078一阶数字低通滤波器推导和相位延迟计算
- 计划任务-定时关闭、重启软件