计算机网络之三次握手四次挥手

计算机网络之三次握手四次挥手

相信学过计算机网络的小伙伴们其他的可以不知道,但是三次握手四次挥手可是不能不知道的呀!下面让我们一起来复习一下这个知识点吧!通过两个不错的视频进行复习回顾一下!
视频讲解链接:
TCP的三次握手和四次挥手
TCP的三次握手和四次挥手

在这里给大家推荐一个公众号,关于计算机网络的知识很全面,我也是参考了大佬总结的知识进行复习的,公众号为 图解网络
在这里我写出自己的学习以及对三次握手和四次挥手的理解,由于画图过于繁琐,所以我就粘贴了图解中的图,有兴趣的小伙伴可以去微信公众号获得资源进行深入学习!
好了,话不多说,开始今天的学习总结了!

一、前备知识

1、TCP 头部格式和各个部分的代表的含义。

TCP 头部格式
解释如下:

  • 序列号:在建⽴连接时由计算机⽣成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送⼀次数据,就 「累加」⼀次该「数据字节数」的⼤⼩。⽤来解决⽹络包乱序问题。
  • 确认应答号:指下⼀次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数 据都已经被正常接收。⽤来解决不丢包的问题。
  • 控制位
    - ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建⽴连接时的 SYN 包之外该位必 须设置为 1 。
    - RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
    - SYN:该位为 1 时,表示希望建⽴连接,并在其「序列号」的字段进⾏序列号初始值的设定。
    - FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双⽅的 主机之间就可以相互交换 FIN 位为 1 的 TCP 段。

2、TCP和UDP的区别?

思维导图:TCP和UDP的区别

二、TCP的三次握手–建立连接

  • 三次握手图解:
    三次握手
    过程如下:
  • ⼀开始, 客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝,处于 LISTEN 状态
  • 第一次握手: 客户端会随机初始化序号( client_isn ),将此序号置于 TCP ⾸部的「序号」字段中,同时把 SYN 标志 位置为 1 ,表示 SYN 报⽂。接着把第⼀个 SYN 报⽂发送给服务端,表示向服务端发起连接,该报⽂不 包含应⽤层数据,之后客户端处于 SYN-SENT 状态。第一次握手
  • 第二次握手: 服务端收到客户端的 SYN 报⽂后,⾸先服务端也随机初始化⾃⼰的序号( server_isn ),将此序号填⼊TCP ⾸部的「序号」字段中,其次把 TCP ⾸部的「确认应答号」字段填⼊ client_isn + 1 , 接着把 SYN 和 ACK 标志位置为 1 。最后把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于 SYN- RCVD 状态。第二次握手
  • 第三次握手: 客户端收到服务端报⽂后,还要向服务端回应最后⼀个应答报⽂,⾸先该应答报⽂ TCP ⾸部 ACK 标志位 置为 1 ,其次「确认应答号」字段填⼊ server_isn + 1 ,最后把报⽂发送给服务端,这次报⽂可以携带客 户到服务器的数据,之后客户端处于 ESTABLISHED 状态。
  • 服务器收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态。第三次握手
  • 从上⾯的过程可以发现第三次握⼿是可以携带数据的,前两次握⼿是不可以携带数据的。⼀旦完成三次握⼿,双⽅都处于 ESTABLISHED 状态,此时连接就已建⽴完成,客户端和服务端就可以相互发送数据了。

通过上面的图解我们已经充分复习了TCP的三次握手建立连接,我在这里通俗地说一下我的理解:我给你发消息说我想跟你发个很重要的文件,我只是发了消息你收没收到我并不知道,所以你需要给我一个你收到了的回复,此时你只是给我回复了消息,但是你并不知道我有没有收到你给我回复的消息,虽然你不知道但是我肯定知道我收到没收到,所以我要再跟你说一下我收到了你的回复,并且把我想要给你发的文件发给你。

问题补充

1、为什么是三次握⼿?不是两次、四次?

1.1 三次握⼿才可以阻⽌复历史连接的初始化(主要原因)

三次握⼿的⾸要原因是为了防⽌旧的重复连接初始化造成混乱。⽹络环境是错综复杂的,往往并不是如我们期望的⼀样,先发送的数据包,就先到达⽬标主机,可能会由于⽹络拥堵等乱七⼋糟的原因,会使得旧的数据包,先到达⽬标主机,那么这种情况下 TCP 三次握⼿是如何 避免的呢?
避免历史连接
客户端连续发送多次 SYN 建⽴连接的报⽂,在⽹络拥堵情况下:

  • ⼀个「旧 SYN 报⽂」⽐「最新的 SYN 」 报⽂早到达了服务端; 那么此时服务端就会回⼀个 SYN + ACK 报⽂给客户端;
  • 客户端收到后可以根据⾃身的上下⽂,判断这是⼀个历史连接(序列号过期或超时),那么客户端就会发送 RST 报⽂给服务端,表示中⽌这⼀次连接。
  • 如果是两次握⼿连接,就不能判断当前连接是否是历史连接,三次握⼿则可以在客户端(发送⽅)准备发送第三次 报⽂时,客户端因有⾜够的上下⽂来判断当前连接是否是历史连接(客户端在第三次握手的时候会根据SeqNum判断是不是历史连接,如果是两次握手的是没办法判断的):
    - 如果是历史连接(序列号过期或超时),则第三次握⼿发送的报⽂是 RST 报⽂,以此中⽌历史连接;
    - 如果不是历史连接,则第三次发送的报⽂是 ACK 报⽂,通信双⽅就会成功建⽴连接;
  • 所以,TCP 使⽤三次握⼿建⽴连接的最主要原因是防⽌历史连接初始化了连接。

通俗理解:客户端第一次发的连接以为网络或者其他原因延时没有准时到达服务端,客户端又发起了第二次连接,但是第一次连接比第二次连接现行到达,但是对于服务器端它是不知道这个连接是第一次还是第二次的连接,所以会给客户端回复确认信息,客户端受到确认信息通过比较SeqNum可判断是第一次还是第二次连接,如果是第一次的连接则回复RST报文给服务端一中止第一次的连接。然后等第二次的连接到达服务端,服务端返回确认信息,客户端通过SeqNum确认是第二次的连接,则回复服务端确认信息,进行连接的建立。

1.2 三次握⼿才可以同步双⽅的初始序列号

TCP 协议的通信双⽅, 都必须维护⼀个「序列号」, 序列号是可靠传输的⼀个关键因素,它的作⽤:

  • 接收⽅可以去除复的数据;
  • 接收⽅可以根据数据包的序列号按序接收;
  • 可以标识发送出去的数据包中, 哪些是已经被对⽅收到的;
  • 可⻅,序列号在 TCP 连接中占据着⾮常要的作⽤,所以当客户端发送携带「初始序列号」的 SYN 报⽂的时 候,需要服务端回⼀个 ACK 应答报⽂,表示客户端的 SYN 报⽂已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应,这样⼀来⼀回,才能确保双⽅的初始序列号能被可靠的同步。

四次握⼿其实也能够可靠的同步双⽅的初始化序号,但由于第⼆步和第三步可以优化成⼀步,所以就成了「三次握 ⼿」。⽽两次握⼿只保证了⼀⽅的初始序列号能被对⽅成功接收,没办法保证双⽅的初始序列号都能被确认接收。
四次握手

通俗理解:我第一次给你发消息的时候带上我的序列号,你收到了给我回复了确认消息并带上了你的序列号,但此时只是我知道你收到了我的序列号,但是你不知道我是否收到了你的序列号,所以我必须给你再回复一个确认信息让你知道我收到了你的序列号。这样我们两个人都知道对方已经收到自己的序列号了。

1.3 三次握⼿才可以避免资源浪费

如果只有「两次握⼿」,当客户端的 SYN 请求连接在⽹络中阻塞,客户端没有接收到 ACK 报⽂,就会新发 送 SYN ,由于没有第三次握⼿,服务器不清楚客户端是否收到了⾃⼰发送的建⽴连接的 ACK 确认信号,所以 每收到⼀个 SYN 就只能先主动建⽴⼀个连接,这会造成什么情况呢?

  • 如果客户端的 SYN 阻塞了,复发送多次 SYN 报⽂,那么服务器在收到请求后就会建⽴多个冗余的⽆效链 接,造成不必要的资源浪费。即两次握⼿会造成消息滞留情况下,服务器复接受⽆⽤的连接请求 SYN 报⽂,⽽造成复分配资源。两次握手
    通俗理解:当我第一次给你发请求建立连接的消息,由于网络的原因第一次延时到达,但是我不想等了所以我又发起了第二次连接,这一次网络很好很快你就收到了并且回复了我确认消息,我们之间建立起了连接,然而之后我第一次给你发的消息你收到了,你又给回复了我一个确认信息并建立了连接,但是你并不知道这次的连接是不是历史连接,但是我知道是不是历史连接,但是由于只有两次握手就算我知道是历史连接我也没办法给你发送请求断开历史连接的消息,以至于历史连接建立了但是也不用,浪费了资源。

TCP 建⽴连接时,通过三次握⼿能防⽌历史连接的建⽴,能减少双⽅不必要的资源开销,能帮助双⽅同步初始化序 列号。序列号能够保证数据包不复、不丢弃和按序传输。
不使⽤「两次握⼿」和「四次握⼿」的原因:

  • 两次握⼿:⽆法防⽌历史连接的建⽴,会造成双⽅资源的浪费,也⽆法可靠的同步双⽅序列号;
  • 四次握⼿:三次握⼿就已经理论上最少可靠连接建⽴,所以不需要使⽤更多的通信次数。

2、为什么客户端和服务端的初始序列号 ISN 是不相同的?

  • 如果⼀个已经失效的连接被⽤了,但是该旧连接的历史报⽂还残留在⽹络中,如果序列号相同,那么就⽆法分辨 出该报⽂是不是历史报⽂,如果历史报⽂被新的连接接收了,则会产⽣数据错乱。所以,每次建⽴连接前新初始化⼀个序列号主要是为了通信双⽅能够根据序号将不属于本连接的报⽂段丢弃。
  • 另⼀⽅⾯是为了安全性,防⽌⿊客伪造的相同序列号的 TCP 报⽂被对⽅接收。

三、TCP的四次挥手–断开连接

  • 四次挥手图解:
    四次挥手
    对于 TCP 连接也是这样, TCP 断开连接是通过四次挥⼿⽅式。 双⽅都可以主动断开连接,断开连接后主机中的「资源」将被释放。
  • 客户端打算关闭连接,此时会发送⼀个 TCP ⾸部 FIN 标志位被置为 1 的报⽂,也即 FIN 报⽂,之后客 户端进⼊ FIN_WAIT_1 状态。
  • 服务端收到该报⽂后,就向客户端发送 ACK 应答报⽂,接着服务端进⼊ CLOSED_WAIT 状态。
  • 客户端收到服务端的 ACK 应答报⽂后,之后进⼊ FIN_WAIT_2 状态。
  • 等待服务端处理完数据后,也向客户端发送 FIN 报⽂,之后服务端进⼊ LAST_ACK 状态。
  • 客户端收到服务端的 FIN 报⽂后,回⼀个 ACK 应答报⽂,之后进⼊ TIME_WAIT 状态
  • 服务器收到了 ACK 应答报⽂后,就进⼊了 CLOSED 状态,⾄此服务端已经完成连接的关闭。
  • 客户端在经过 2MSL ⼀段时间后,⾃动进⼊ CLOSED 状态,⾄此客户端也完成连接的关闭。
  • 这⾥⼀点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

再来回顾下四次挥⼿双⽅发 FIN 包的过程,就能理解为什么需要四次了:

  • 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
  • 服务器收到客户端的 FIN 报⽂时,先回⼀个 ACK 应答报⽂,⽽服务端可能还有数据需要处理和发送,等 服务端不再发送数据时,才发送 FIN 报⽂给客户端来表示同意现在关闭连接。
    从上⾯过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN ⼀般都会分开发 送,从⽽⽐三次握⼿导致多了⼀次。

TCP 四次挥手断开连接 通俗理解:
我给你发消息说我要跟你分手,我在等你回消息,但是你可能在忙,你回复我一个等下哦,我正在忙,忙完会跟你说的,我收到你的回复知道你在忙我就乖乖等你忙完,你忙完了之后回复我:好的,我知道你要分手了,那就分手吧,我收到你的消息会回复你,我收到你的消息了,知道可以分手了。然后你就下线了,我还在等,害怕你再给我发什么消息,等一段时间没什么消息了我也就下线了,至此我们就完成了分手。如果谈恋爱也这样多好,一点儿都不拖拉,哈哈哈哈哈!

问题补充

1、为什么 TIME_WAIT 等待的时间是 2MSL?

  • MSL 是 Maximum Segment Lifetime,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。 因为 TCP 报⽂基于是 IP 协议的,⽽ IP 头中有⼀个 TTL 字段,是 IP 数据报可以经过的最⼤路 由数,每经过⼀个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报⽂通知源主机。
  • **MSL 与 TTL 的区别: MSL 的单位是时间,⽽ TTL 是经过路由跳数。**所以 MSL 应该要⼤于等于 TTL 消耗为 0 的时间,以确保报⽂已被⾃然消亡。
  • TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是: ⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包 被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间。⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时发 Fin 报⽂,另⼀⽅接收到 FIN 后, 会发 ACK 给被动关闭⽅, ⼀来⼀去正好 2 个 MSL。
  • 2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。 如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端⼜接收到了服务端发的 FIN 报⽂,那么 2MSL 时间将重新计时。在 Linux 系统⾥ 2MSL 默认是 60 秒,那么⼀个 MSL 也就是 30 秒。Linux 系统停留在 TIME_WAIT 的时间为固定的 60 秒。

2、为什么需要 TIME_WAIT 状态?

主动发起关闭连接的⼀⽅,才会有 TIME-WAIT 状态。
需要 TIME-WAIT 状态,主要是两个原因:

  • 防⽌具有相同「四元组」的「旧」数据包被收到;
  • 保证「被动关闭连接」的⼀⽅能被正确的关闭,即保证最后的 ACK 能让被动关闭⽅接收,从⽽帮助其正常关 闭;
2.1 防⽌旧连接的数据包

假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发⽣什么呢?
没有TIME的影响
如上图⻩⾊框框服务端在关闭连接之前发送的 SEQ = 301 报⽂,被⽹络延迟了。
这时有相同端⼝的 TCP 连接被复⽤后,被延迟的 SEQ = 301 抵达了客户端,那么客户端是有可能正常接收 这个过期的报⽂,这就会产⽣数据错乱等严的问题。
所以,TCP 就设计出了这么⼀个机制,经过 2MSL 这个时间,⾜以让两个⽅向上的数据包都被丢弃,使得原来 连接的数据包在⽹络中都⾃然消失,(MSL 报⽂最⼤⽣存时间)再出现的数据包⼀定都是新建⽴连接所产⽣的。

2.2 保证连接正确关闭

TIME-WAIT 作⽤是等待⾜够的时间以确保最后的 ACK 能让被动关闭⽅接收,从⽽帮助其正常关闭。
假设 TIME-WAIT 没有等待时间或时间过短,断开连接会造成什么问题呢?
第二种影响

  • 如上图红色框客户端四次挥手的最后一个 ACK 报文如果在网络中被丢失了,此时如果客户端TIME-WAIT 过短或没有,则就直接进⼊了 CLOSED 状态了,那么服务端则会⼀直处在 LASE_ACK 状态。
  • 当客户端发起建⽴连接的 SYN 请求报⽂后,服务端会发送 RST 报⽂给客户端,连接建⽴的过程就会被终⽌。
    通俗理解:最后发送的确认信息,没有被服务端收到,但是服务端没有收到客户端是不知道的,如果不等待或者等待时间过短的话,客户端会关闭,服务端还会处于 LAST_ACK 状态,当客户端再发起连接的时候,服务端是应该接收ACK消息的,但是客户端却发起的SYN报文,这样会导致服务端请求终止连接即你想建立新的连接少说也得等我这边关闭了,你才能建立新的连接!

如果 TIME-WAIT 等待⾜够⻓的情况就会遇到两种情况:

  • 服务端正常收到四次挥⼿的最后⼀个 ACK 报⽂,则服务端正常关闭连接。
  • 服务端没有收到四次挥⼿的最后⼀个 ACK 报⽂时,则会发 FIN 关闭连接报⽂并等待新的 ACK 报 ⽂。(⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时发 Fin 报⽂,另⼀⽅接收到 FIN 后, 会发 ACK 给被动关闭⽅, ⼀来⼀去正好 2 个 MSL。)
    所以客户端在 TIME-WAIT 状态等待 2MSL 时间后,就可以保证双⽅的连接都可以正常的关闭。

3、TIME_WAIT 过多有什么危害?

如果服务器有处于 TIME-WAIT 状态的 TCP,则说明是由服务器⽅主动发起的断开请求。 过多的 TIME-WAIT 状态主要的危害有两种:

  • 第⼀是内存资源占⽤
  • 第⼆是对端⼝资源的占⽤,⼀个 TCP 连接⾄少消耗⼀个本地端⼝;

如果发起连接⼀⽅的 TIME_WAIT 状态过多,占满了所有端⼝资源,则会导致⽆法创建新连接。

  • 客户端受端⼝资源限制:
    客户端TIME_WAIT过多,就会导致端⼝资源被占⽤,因为端⼝就65536个,被占满就会导致⽆法创建新的连 接。
  • 服务端受系统资源限制:
    由于⼀个四元组表示 TCP 连接,理论上服务端可以建⽴很多连接,服务端确实只监听⼀个端⼝ 但是会把连接 扔给处理线程,所以理论上监听的端⼝可以继续监听。但是线程池处理不了那么多⼀直不断的连接了。所以 当服务端出现⼤ TIME_WAIT 时,系统资源被占满时,会导致处理不过来新的连接。

4、如果已经建⽴了连接,但是客户端突然出现故障了怎么办?

TCP 有⼀个机制是保活机制。这个机制的原理是这样的:
定义⼀个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作⽤,每隔⼀个时间间 隔,发送⼀个探测报⽂,该探测报⽂包含的数据⾮常少,如果连续⼏个探测报⽂都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应⽤程序。
在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔:

  • tcp_keepalive_time=7200:表示保活时间是 7200 秒(2⼩时),也就 2 ⼩时内如果没有任何连接相关的活 动,则会启动保活机制
  • tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;
  • tcp_keepalive_probes=9:表示检测 9 次⽆响应,认为对⽅是不可达的,从⽽中断本次的连接。

也就是说在 Linux 系统中,最少需要经过 2 ⼩时 11 分 15 秒才可以发现⼀个「死亡」连接。
这个时间是有点⻓的,我们也可以根据实际的需求,对以上的保活相关的参数进⾏设置。

如果开启了 TCP 保活,需要考虑以下⼏种情况:

  • 第⼀种,对端程序是正常⼯作的。当 TCP 保活的探测报⽂发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下⼀个TCP 保活时间的到来。
  • 第⼆种,对端程序崩溃并启。当 TCP 保活的探测报⽂发送给对端后,对端是可以响应的,但由于没有该连接的 有效信息,会产⽣⼀个 RST 报⽂,这样很快就会发现 TCP 连接已经被置。
  • 第三种,是对端程序崩溃,或对端由于其他原因导致报⽂不可达。当 TCP 保活的探测报⽂发送给对端后,⽯沉⼤海,没有响应,连续⼏次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值