三次握手和四次挥手图解_图解 TCP 三次握手和四次挥手

本文详细解析了TCP的三次握手和四次挥手过程,解释了为何需要三次握手以及四次挥手的原因,同时介绍了SYN(洪水)攻击及其防范措施,并对比了TCP与UDP的区别。
摘要由CSDN通过智能技术生成

人到中年,难免长
大家好,我是你们有点严肃的胖福(hu),

这里我们聊学习和工作。b2e639e8c809db63ba91e2094c4ed96e.png

- 内容提要 -

59dd6a713ae6515d82d64fc4da6d89ff.png

TCP 有 6 种标示:SYN(建立联机) ACK(确认) PSH(传送) FIN(结束) RST(重置) URG(紧急)

一、TCP 三次握手

c226076e1af8425e5ec811b37c6d72f2.png

第一次握手

客户端向服务器发出连接请求报文,这时报文首部中的同部位 SYN=1,同时随机生成初始序列号 seq=x,此时,TCP 客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP 规定,SYN 报文段(SYN=1 的报文段)不能携带数据,但需要消耗掉一个序号。这个三次握手中的开始。表示客户端想要和服务端建立连接。

第二次握手

TCP 服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是 ack=x+1,同时也要为自己随机初始化一个序列号 seq=y,此时,TCP 服务器进程进入了 SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。这个报文带有 SYN(建立连接)和 ACK(确认)标志,询问客户端是否准备好。

第三次握手

TCP 客户进程收到确认后,还要向服务器给出确认。确认报文的 ACK=1,ack=y+1,此时,TCP 连接建立,客户端进入 ESTABLISHED(已建立连接)状态。

TCP 规定,ACK 报文段可以携带数据,但是如果不携带数据则不消耗序号。这里客户端表示我已经准备好。

思考:为什么要三次握手呢,有人说两次握手就好了

举例:已失效的连接请求报文段。

client 发送了第一个连接的请求报文,但是由于网络不好,这个请求没有立即到达服务端,而是在某个网络节点中滞留了,直到某个时间才到达 server,本来这已经是一个失效的报文,但是 server 端接收到这个请求报文后,还是会向 client 发出确认的报文,表示同意连接。假如不采用三次握手,那么只要 server 发出确认,新的建立就连接了,但其实这个请求是失效的请求,client 是不会理睬 server 的确认信息,也不会向服务端发送确认的请求,但是 server 认为新的连接已经建立起来了,并一直等待 client 发来数据,这样,server 的很多资源就没白白浪费掉了,采用三次握手就是为了防止这种情况的发生,server 会因为收不到确认的报文,就知道 client 并没有建立连接。这就是三次握手的作用。

二、TCP 数据的传输过程

建立连接后,两台主机就可以相互传输数据了。如下图所示(本篇博客图片都是引用它人图片):

5876eb1b43495f5d7bd646c2f47c871a.png
  1. 主机 A 初始 seq 为 1200,滑动窗体为 100,向主机 B 传递数据的过程。

  2. 假设主机 B 在完全成功接收数据的基础上,那么主机 B 为了确认这一点,向主机 A 发送 ACK 包,并将 ack 号设置为 1301。因此按如下的公式确认 ack 号:

ack 号 = qeq 号 + 传递的字节数 + 1 (这是在完全接受成功的情况下)

  1. 主机 A 获得 B 传来的 ack(1301) 后,开始发送 seq 为 1301,滑动窗体为 100 的数据。

与三次握手协议相同,最后加 1 是为了告诉对方要传递的 seq 号。上面说了,主机 B 完全成功接收 A 发来的数据才是这样的,如果存在丢包该如何?

下面分析传输过程中数据包丢失的情况,如下图所示:

d1f6deb9c8e0bb87459d4f14a205491c.png

上图表示通过 seq 1301 数据包向主机 B 传递 100 字节的数据,但中间发生了错误,主机 B 未收到。经过一段时间后,主机 A 仍未收到对于 seq 1301 的 ACK 确认,因此尝试重传数据。为了完成数据包的重传,TCP 套接字每次发送数据包时都会启动定时器,如果在一定时间内没有收到目标机器传回的 ACK 包,那么定时器超时,数据包会重传。

上面也只是一种可能,比如数据 1250 丢失,那么 ACK 返回的就是 1250,具体的可以详细看下博客:【TCP 协议】(1)---TCP 协议详解,这里面滑动窗口有说明。

三、TCP 的四次挥手

b9248d2d6a25aeef5c7c1f6654f3bbcc.png

第一次挥手

TCP 发送一个 FIN(结束),用来关闭客户到服务端的连接。

客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为 seq=u(等于前面已经传送过来的数据的最后一个字节的序号加 1),此时,客户端进入 FIN-WAIT-1(终止等待 1)状态。TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。

第二次挥手

服务端收到这个 FIN,他发回一个 ACK(确认),确认收到序号为收到序号+1,和 SYN 一样,一个 FIN 将占用一个序号。

服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号 seq=v,此时,服务端就进入了 CLOSE-WAIT(关闭等待)状态。TCP 服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个 CLOSE-WAIT 状态持续的时间。

客户端收到服务器的确认请求后,此时,客户端就进入 FIN-WAIT-2(终止等待 2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

第三次挥手

服务端发送一个 FIN(结束)到客户端,服务端关闭客户端的连接。

服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w,此时,服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手

客户端发送 ACK(确认)报文确认,并将确认的序号+1,这样关闭完成。

客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是 seq=u+1,此时,客户端就进入了 TIME-WAIT(时间等待)状态。注意此时 TCP 连接还没有释放,必须经过 2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的 TCB 后,才进入 CLOSED 状态。

服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。可以看到,服务器结束 TCP 连接的时间要比客户端早一些。

思考:那么为什么是 4 次挥手呢?

为了确保数据能够完成传输。

关闭连接时,当收到对方的 FIN 报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭 SOCKET,也即你可能还需要发送一些数据给对方之后,再发送 FIN 报文给对方来表示你同意现在可以关闭连接了,所以它这里的 ACK 报文和 FIN 报文多数情况下都是分开发送的。

可能有人会有疑问,tcp 我握手的时候为何 ACK(确认)和 SYN(建立连接)是一起发送。挥手的时候为什么是分开的时候发送呢。

因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,"你发的 FIN 报文我收到了"。只有等到我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步挥手。

思考:客户端突然挂掉了怎么办?

正常连接时,客户端突然挂掉了,如果没有措施处理这种情况,那么就会出现客户端和服务器端出现长时期的空闲。解决办法是在服务器端设置保活计时器,每当服务器收到客户端的消息,就将计时器复位。超时时间通常设置为 2 小时。若服务器超过 2 小时没收到客户的信息,他就发送探测报文段。若发送了 10 个探测报文段,每一个相隔 75 秒,还没有响应就认为客户端出了故障,因而终止该连接。

四、SYN(洪水)攻击

背景

初始化连接的 SYN 超时问题 Client 发送 SYN 包给 Server 后挂了,Server 回给 Client 的 SYN-ACK 一直没收到 Client 的 ACK 确认,这个时候这个连接既没建立起来,也不能算失败。这就需要一个超时时间让 Server 将这个连接断开,否则这个连接就会一直占用 Server 的 SYN 连接队列中的一个位置,大量这样的连接就会将 Server 的 SYN 连接队列耗尽,让正常的连接无法得到处理。

目前,Linux 下默认会进行 5 次重发 SYN-ACK 包,重试的间隔时间从 1s 开始,下次的重试间隔时间是前一次的双倍,5 次的重试时间间隔为 1s, 2s, 4s, 8s, 16s,总共 31s,第 5 次发出后还要等 32s 都知道第 5 次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP 才会把断开这个连接。由于,SYN 超时需要 63 秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的 SYN 包给 Server(俗称 SYN flood 攻击),用于耗尽 Server 的 SYN 队列。

什么是 SYN 攻击

SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS 攻击。

如何检测 SYN 攻击?

检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击。在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击。

如何防御 SYN 攻击?

SYN 攻击不能完全被阻止,除非将 TCP 协议重新设计。我们所做的是尽可能的减轻 SYN 攻击的危害,常见的防御 SYN 攻击的方法有如下几种:

  • 缩短超时(SYN Timeout)

  • 时间增加最大半连接数

  • 过滤网关防护 SYN

  • cookies 技术

五、TCP 和 UDP 的区别

我这里简单列举几个,因为我还没有研究 UDP 这个协议。

  1. 基于连接与无连接:UDP 是无连接的,即发送数据之前不需要建立连接。

  2. TCP 保证数据正确性,UDP 可能丢包,TCP 保证数据顺序,UDP 不保证。也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。TCP 通过校验和、重传控制、序号标识、滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。

  3. UDP 具有较好的实时性,工作效率比 TCP 高,适用于对高速传输和实时性有较高的通信或广播通信。

  4. 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信。

  5. TCP 对系统资源要求较多,UDP 对系统资源要求较少。


作者:雨点的名字

链接:https://www.cnblogs.com/qdhxhz/p/8470997.html


如果你看完本文有收获,欢迎关注微信公众号:精进Java(ID: craft4j),更多 Java 后端与架构的干货等你一起学习与交流。

fd5d45fd8c27d0ea98c27200ecc30851.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值