TCP | 青训营笔记

157 阅读8分钟

可靠性

  • 基于数据块传输:TCP会把应用层传下来的数据,分割成合适的块再进行传输
  • TCP三次握手:对报文序号进行校验
  • ARQ自动重传协议:超时重传
  • 流量控制
  • 拥塞控制

理解

TCP是一个可靠的端到端传输协议。它通过建立连接、按序收发、丢包重传、流量控制、拥塞控制等方式来保证传输的可靠性。建立连接时确保双方的收发能力并互相同步初始序列号,初始序列号的同步保证之后的按序收发和重传能够实现。流量控制是发送方根据接收方的接收能力来控制发送报文段的数量,这样能够减少因接收方缓存不够而丢包的情况。拥塞控制是根据整个网络链路的情况,来控制发送数量。

TCP三次握手

三次握手的目的是为了通过同步双方数据的序列号来保证可靠传输。 保证双方的收发能力、阻止重复历史连接的初始化。

握手过程

  1. C发送同步信号位SYN = 1和原始序列号x。发送后客户端进入SYN_SEND状态。
  2. S接收到C发送的原始序列号,记在本地,并标记确认序号ack = x + 1,和确认信号位ACK = 1。发送后服务端进入SYN_RECV状态。
  3. S也需要告知C自己的原始序列号,同样发送SYN = 1和原始序列号y。
  4. C收到S的原始序列号后,记在本地,并标记确认序号ack = y + 1,和确认信号位ACK = 1。客户端进入ESTABLISHED状态。

上述过程的2.3两步合并,所以就形成了三次握手。 看了上面的过程就知道为什么一定要三次握手,因为双方都需要确认对方已经同步自己的原始序列号。

握手时会出现的异常

  1. 当第一次握手丢失,C会进行超时重传,重传次数和超时时间都是内核参数决定的。
  2. 当第二次握手丢失,这时候会影响到C和S双方。C会以为自己的包没有发送,进行超时重传;S没有收到C的确认也会进行超时重传。
  3. 当第三次握手丢失,这时候S会认为自己的报文没有送达,进行超时重传。而C在发送完第三个握手后,就进入了ESTABLISH状态,并且ACK报文不会重传,所以不会管这个异常。

关于序列号的更新

TCP规定SYN和FIN报文即使没有内容也是占一个序列号,而ACK报文可以携带数据,但如果不携带数据则序列号不增。所以第三次握手后,A发送数据时序列号与第三次握手的相同。

四次挥手

挥手过程

  1. C发送释放报文FIN = 1、seq = u,告知服务器将要结束会话,并且之后不会再发送数据。发送后客户端进入FIN_WAIT1状态。
  2. S收到C的释放报文,返回一个确认报文,ACK = 1,ack = u+ 1,seq = v。但此时没有立刻结束,因为S可能还有数据要发送,而C也要继续接受S的数据。发送后服务端进入CLOSE_WAIT状态。
  3. 客户端收到服务端的ACK后,进入FIN_WAIT2状态
  4. S发送完数据后也可以释放会话了,就发送释放报文FIN = 1、seq = w、ACK = 1,ack = u+ 1。发送后服务端进入LAST_ACK状态。
  5. C收到S的释放报文后,返回确认报文ACK = 1、ack = w + 1、seq = u + 1,然后进入TIME_WAIT状态,并等到2*MSL后才进入CLOSED状态。
  6. S只要收到了C的确认报文,立刻进入CLOSED状态。

为什么需要四次挥手

与三次握手一样,需要保证双方都知道结束会话这个消息;与三次握手不同的是,挥手时2、3两步无法合并成一步,因为S可能还有数据没传完。

为什么要等待两个MSL

MSL是最长报文段寿命。为了防止返回的确认报文丢失,如果确认报文丢失,则S会超时重传释放报文,能够在两个MSL内重新发送到C,C就再一次发送确认报文并重新开始计时。【思考:如果S第二次发的报文丢了,那么C不会等S,会直接结束会话,怎么办?见异常分析】

挥手会出现的异常

  1. 第一次释放报文丢失,C会进行超时重传,和普通报文一样,重传机制由OS控制。
  2. 第二次确认报文丢失,ACK报文是不会进行重传的,而C没有收到就会重传释放报文。
  3. 第三次释放报文丢失,S会进行重传。如果此时C等待了一段时间一直没有收到S的释放报文,会主动关闭会话。
  4. 第四次确认报文丢失,S会进行重传,如果C此时已经结束会话,S也会在达到重传次数后认为异常,主动关闭会话。

流量控制

流量控制是针对接收方,确保接收方有足够的缓存来接收发送方的数据。 发送方维护一个发送窗口,接收方维护一个接收窗口,并且发送窗口是根据接收窗口来决定的。

发送窗口

可以分为四个部分:1、已发送已确认;2、已发送未确认;3、可发送;4、不可发送;

接收窗口

可以分为三个部分:1、已接收已确认;2、等待接收;3、不可接收

拥塞控制

拥塞控制针对整个网络的链路,确保发送方提供的数据量能够在网络中正常传送。发送方维护一个拥塞窗口,让发送窗口等于拥塞窗口,但实际上考虑到流量控制,还要与接收方的接收窗口对比,取较小值。

慢开始算法

拥塞窗口从1开始,每经过一个RTT(Round Trip Time:往返时间)就让拥塞窗口翻倍,这时候拥塞窗口是指数增长。

拥塞避免

在慢开始算法有一个慢开始门限ssthresh,当拥塞窗口超过这个值时,就开始拥塞避免算法。此时拥塞不是真的发生了,而是为了避免拥塞降低了拥塞窗口的增长速度。从每个RTT翻倍,变为每个RTT增加1。 当拥塞发生时(超时就可以被判断为拥塞),将ssthresh将为当前拥塞窗口的一半,并让拥塞窗口从1重新开始慢开始算法。

快重传

要求接收方接收到不期待的序号时,立即返回一个重复确认报文,当发送方收到三个相同序号的确认报文时,认为某个报文已经丢失,立刻进行重传。

快恢复

当拥塞发生时,不从1开始恢复拥塞窗口,而是降低到新的ssthresh,即拥塞发生时拥塞窗口的一半,然后进行线性增加窗口大小。

ARQ 自动重传协议

停止等待

发送一个报文就停下来,等待接收方给返回。在超时后没有接收到返回则自动重传。

连续

发送方维护窗口,一次性将窗口内的内容全部发送,根据接收方的返回来更新窗口。接收方可以使用累计确认来对接收到的最后一个报文进行确认,表明这之前的报文都正确接收了。

思考

二次握手可以吗?

不行。如果只有两次握手,服务端无法确保客户端的接收能力正常,且无法确保已成功与对方同步自己的初始序列号。

三次握手可以携带数据吗

第三次可以携带数据。客户端发出第三次握手时已经确保服务端的接收能力正常,因此可以放心的发送数据。

为什么不能是三次挥手

三次握手其实是将第二次和第三次握手合成了一次。而断开连接时服务端很可能还没结束数据传输,因此无法合成一步。

为什么要等待两个最长报文段寿命

防止最后一个确认包丢失,给服务端重传FIN报文留出时间。还能够避免新旧连接混淆,经过两个最长报文段寿命后,可以确保当前连接的报文都从网络中消失。

与UDP区别

UDP不面向连接,也不保证可靠的端到端传输。对应用层传下的数据报不进行处理,只进行简单的封装。由于不基于连接所以速度比较快,而且它的头部开销小,只有8B。