暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TCP三次握手,四次挥手。生动理解,再也不忘

阿斌Java之路 2022-05-29
849

传输层的协议有UDP和TCP,基本能解决99%以上的问题,所以不需要再有第三个协议。在了解TCP和UDP之前,我们需要先了解计算机网络中可靠协议的演进。

可靠性传输RDT(Reliable Data Transfer)

数据的可靠传输是计算机网络中的通用概念,也是UDP和TCP的基石。计算机五层模型中,上层需要借助下层提供的功能来完成数据的传输,那么如果下层不可靠,我们该如何保证数据的可靠传输?接下来会一步步假设,一步步的暴露问题,来看看可靠性传输RDT是如何演进的?

RDT1.0

对应场景
:下层的信道是完全可靠的:没有比特差错,没有分组丢失

发送方和接收方的FSM:发送方将数据发送到下层信道,接收方从下层信道接收数据

所以rdt1.0做的工作就是封装和解封装

RDT2.0

对应场景
:下层信道可能出现差错:将分组中的比特翻转,0变为1,1变为0

应对手段

  • 校验和
    :用校验和的方式进行差错检测
  • 确认ACK
    :接收方显式的告诉发送方分组已经被接收
  • 否定确认NAK
    :接收方显式地告诉发送方分组出现了差错(发送方接收到NAK后,会重传分组)

过程描述
:发送方发送packet到下层信道,接收方接收,通过校验和发现数据有差错,返回NAK,发送方再次发送原packet;无差错返回ACK,发送方发送新的pactet

所以Rdt2.0新机制就是采用了差错控制编码进行差错检测

存在问题
:发送的packet可能会出现错误,但是返回的ACK NAK是不是就一定是正确的呢?答案肯定是否定的,但是发送方应该怎么做呢?重传?可能会重复,不重传?可能会造成死锁或出错

所以引出了 Rdt2.1

RDT2.1

对应场景
:2.0中接收方返回的ack/nack有可能出错,如果重传数据,还有可能重复。

应对手段

  • 加上序号
    :给每个packet加上序号,哪怕客户端接收到重复数据,也能判断到重复。
  • 停止等待
    :发送方只发送一个分组,然后等待接收方的应答的方式称为停止等待协议

RDT2.1(无NACK)

对应场景
:发送方需要识别ACK和NACK两套状态管理,太复杂了

应对手段

  • 取消NACK
    :取消了NACK的方式,那么接收方怎么告诉发送方数据错了呢?可以通过返回ACK+上一个packet的序号的方式返回。
  • 重复ACK
    :当接收方收到重复的ACK时,说明下一个packet发送失败了。接收方会重发当前ACK序号后的报文

存在问题
:返回的ACK也有可能丢失,发送方就会一直等待确认。

所以引出了 Rdt3.0

RDT3.0

对应场景
:发送方会一直等待ACK,但是ACK有可能丢失

应对手段

  • 定时器
    :增加一个定时器,对应时间内没收到ACK就直接触发超时重传机制。

存在问题
:RDT3.0以及之前,一直采用停止等待协议,也就是一个包没收到响应就不会发送下一个,信道利用率太低。由此引入了流水线协议。

停止等待协议

先明白一个概念WS(window size)代表可发送,或者可接收的窗口的长度。在停止等待协议中,发送方只能发送一个分组,等待确认后,再发送下一个,所以。

发送方窗口=1

接收方窗口=1

流水线协议

为了提高信道的利用率,我们需要能够批量发送分组。当发送方窗口>1,我们称之为流水线协议。

GBN(Go-Back-N )

img

接收方窗口=1,发送方窗口=N。

  • 重传定时器
    :发送方只为最早的未经确认的分组维护一个定时器,如果产生超时,将重新发送该分组后的所有分组,也就是顾名思义的回退N步。
  • 丢弃乱序
    :接收方窗口只有1,如果接收到比较大的序号分组,都会选择丢弃。

SR(Selective Repeat)

img

接收方窗口=N,发送方窗口=N。

  1. 重传定时器
    :发送方为每个分组都设置了重传定时器,如果触发重传,只需要重传某个分组即可
  2. 乱序接收
    :接收方可以乱序接收分组,当最头部分组整体接收完毕,滑动窗口可以整体后移,并将头部接收到的多个分组整体提交给上层。
img

TCP

报文结构

img

URG:紧急指针

ACK:是否确认应答消息

PSH:是否立即从缓冲区取走数据

RST:复位标识

SYN:同步序列号标识(TCP连接时使用)

FIN:结束序列号标识(TCP断开时使用)

16位窗口----不是滑动窗口的大小,滑动窗口的大小是固定的,他是用来记录接受缓冲区的大小,如果大小为0,就不会发送数据了。以此达到流量控制。

关于序号seq和确认号ack,我们可以展开说说。seq的值代表当前报文的发送序号,ack中的值代表接收方需要的数据将从对方哪个序号开始。

所以 响应ACK=请求SEQ+请求字节数

img

捎带技术

TCP是全双工的,在接收方返回ACK的时候,同时还需要向对方传输一些数据,这时候可以将数据和ACK报文合并成一个分组,称之为捎带技术

可靠性与顺序传输

TCP是一种流水线的传输方式,那么TCP属于GBN 还是属于SR呢,其实TCP是GBN和SR的混合体

  • 顺序接收
    :因为有了分组编号,接收方收到乱序的分组后,不会选择丢弃,而是缓存起来,排好序。返回的ACK仍然是第一个未收到的分组序号。
  • 超时重传
    :tcp发送方只为最早的分组设置一个定时器,当分组未收到ACK触发超时重传,并获得ACK应答后,才开始为下一个未确认分组开始计时。
  • 快速重传
    :基于接收方ACK确认机制,ACK序号为按顺序第一个未收到的分组。发送方接收到三次相同的ACK序号后,会触发快速重传机制,重传ACK序号标识的分组。
  • 选择确认
    :发送方未接收到分组的ACK时,只会重新发送单个分组,而不会发送所有分组。

流量控制

如果接收方的接受速率不足,发送方就应该减缓发送的速率,避免接收方溢出。发送速率的控制是通过发送的滑动窗口大小来控制的。

通过上面的报文,我们能看见16位的窗口大小。这个窗口,就是接收方维护的一块变量,值代表接收方缓冲区还剩余多少可用的缓存空间。

拥塞控制

有时,发送方和接收方性能后很好,结果是中途的网络带宽不行,网络中堵塞了。这时候如果还是依然大量的发送消息,反而会造成更大面积的网络拥塞。

如何感知网络拥塞?我们可以通过丢包率来判断,根据对应的公式,算出网络拥塞下的发送速率该有多大,进而求出当前的滑动窗口大小。

TCP的连接速率是一个慢启动的过程,

  • 一开始滑动窗口只有1。

  • 每一次收到ACK,都会成倍的增加滑动窗口大小。

  • 每一次快速重试都会降为一半。

  • 每一次超时重传,都会降为1.

联合控制

滑动窗口是由流量控制和拥塞控制共同决定的。WS=min(拥塞窗口,流量控制窗口)

连接管理

到了我们最感兴趣的八股文环节,来说说TCP的三次握手,和四次挥手

三次握手

img
  • SYN:连接请求/接收 报文段
  • seq:发送的第一个字节的序号
  • ACK:确认报文段
  • ack:确认号。希望收到的下一个数据的第一个字节的序号

刚开始客户端处于 Closed 的状态,而服务端处于 Listen 状态

CLOSED :没有任何连接状态

LISTEN :侦听来自远方 TCP 端口的连接请求

1)第一次握手:客户端向服务端发送一个 SYN 报文(SYN = 1),并指明客户端的初始化序列号 ISN(x),即图中的 seq = x,表示本报文段所发送的数据的第一个字节的序号。此时客户端处于 SYN_Send 状态。

SYN-SENT :在发送连接请求后等待匹配的连接请求

2)第二次握手:服务器收到客户端的 SYN 报文之后,会发送 SYN 报文作为应答(SYN = 1),并且指定自己的初始化序列号 ISN(y),即图中的 seq = y。同时会把客户端的 ISN + 1 作为确认号 ack 的值,表示已经收到了客户端发来的的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 x + 1,此时服务器处于 SYN_REVD 的状态。

SYN-RECEIVED:在收到和发送一个连接请求后等待对连接请求的确认

3)第三次握手:客户端收到服务器端响应的 SYN 报文之后,会发送一个 ACK 报文,也是一样把服务器的 ISN + 1 作为 ack 的值,表示已经收到了服务端发来的的 SYN 报文,希望收到的下一个数据的第一个字节的序号是 y + 1,并指明此时客户端的序列号 seq = x + 1(初始为 seq = x,所以第二个报文段要 +1),此时客户端处于 Establised 状态。

服务器收到 ACK 报文之后,也处于 Establised 状态,至此,双方建立起了 TCP 连接。

ESTABLISHED:代表一个打开的连接,数据可以传送给用户

为什么要三次握手?

三次握手的本质是,双方都要发出连接请求,交换自己的序列seq,并确认对方能够正常接收做出应答。本来是两个往返需要四次,服务器这边将应答和请求合并了,所以只需要三次。

两次握手行不行?

两次握手相当于省略了第三次应答,服务器没法确认对方收到了自己的序列号。本来服务器在接收到对方第一次请求的时候进入的是半开状态,还没建立连接。两次握手意味着接收到对方请求后,服务器就直接进入了连接状态,能直接发送数据。这时候对方没接收到第二次的应答,没协商好seq序号就发送消息,会产生错乱。

第三次握手丢失了会怎样?

服务器在发出第二次握手后,会进入半开 SYN_REVD 的状态。等待第三次握手,如果第三次握手没有达到,会触发超时重传。例如间隔时间为 1s,2s,4s,8s…

SYN 洪泛攻击?

SYN 攻击就是 Client 在短时间内伪造大量不存在的 IP 地址,并向 Server 不断地发送 SYN 包,Server 则回复确认包,并等待 Client 确认,由于源地址不存在,因此 Server 需要不断重发直至超时,这些伪造的 SYN 包将长时间占用半连接队列,导致正常的 SYN 请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪

四次挥手

img

回顾一下上图中符号的意思:

  • FIN :连接终止位
  • seq:发送的第一个字节的序号
  • ACK:确认报文段
  • ack:确认号。希望收到的下一个数据的第一个字节的序号

刚开始双方都处于ESTABLISHED 状态,假设是客户端先发起关闭请求。四次挥手的过程如下:

1)第一次挥手:客户端发送一个 FIN 报文(请求连接终止:FIN = 1),报文中会指定一个序列号 seq = u。并停止再发送数据,主动关闭 TCP 连接。此时客户端处于 FIN_WAIT1 状态,等待服务端的确认。

FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;

2)第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。

CLOSE-WAIT - 等待从本地用户发来的连接中断请求;

此时的 TCP 处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待 2)状态,等待服务端发出的连接释放报文段。

FIN-WAIT-2 - 从远程TCP等待连接中断请求;

3)第三次挥手:如果服务端也想断开连接了(没有要向客户端发出的数据),和客户端的第一次挥手一样,发送 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态,等待客户端的确认。

LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;

4)第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答(ack = w+1),且把服务端的序列值 +1 作为自己 ACK 报文的序号值(seq=u+1),此时客户端处于 TIME_WAIT (时间等待)状态

TIME-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认;

🚨 注意 !!!这个时候由服务端到客户端的 TCP 连接并未释放掉,需要经过时间等待计时器设置的时间 2MSL(一个报文的来回时间) 后才会进入 CLOSED 状态(这样做的目的是确保服务端收到自己的 ACK 报文。如果服务端在规定时间内没有收到客户端发来的 ACK 报文的话,服务端会重新发送 FIN 报文给客户端,客户端再次收到 FIN 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文给服务端)。服务端收到 ACK 报文之后,就关闭连接了,处于 CLOSED 状态。

为什么要四次挥手?

由于 TCP 的半关闭(half-close)特性,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。

通俗的来说,两次握手就可以释放一端到另一端的 TCP 连接,完全释放连接一共需要四次握手。

或者这么理解,其实建立连接和释放连接都需要四次。双方的请求加双方的应答。但是建立连接可以合并应答和请求。而释放连接,可能服务器还有需要发送的数据,没法合并,只能先应答,发完剩下的组后,再请求关闭。

UDP

img
  • UDP长度,总共16位,占两个字节
  • UDP报文长度=UDP报头(首部)+UDP载荷
  • 该字段保存了UDP报文的长度,单位为字节
  • 2个字节能表示的数据范围是0~65535,也就是能够表示的报文长度是65536字节(Byte),转换成KB,65536/1024 = 64 KB 这就是一个UDP报文所能表示的最大长度.

tcp和udp差别

面向连接的----------无连接

可靠的----------------尽最大努力交付

有序的----------------无序

速度慢----------------速度快

重量级----------------轻量级

适合对可靠性要求高的-----------适合电话,视频,直播





END



后台回复关键词 计算机网络 获取今日推荐资料

微信8.0新增了一万的好友数,之前没加上好友的可以加一下我的个人微信,再晚又满了,一起抱团取暖结伴内卷。



扫码拉群,学习打卡,交流经验


每周一读




文章转载自阿斌Java之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论