走进TCP协议——详解“三次握手”与“四次挥手”

前言

轻轻的我走了,正如我轻轻的来;我轻轻的招手,作别西天的云彩。
悄悄的我走了,正如我悄悄的来;我挥一挥衣袖,不带走一片云彩。
——节选自《再别康桥》徐志摩

相比于诗人的“招手”、“挥手”有木有感觉TCP协议的“握手”、“挥手”更加具有逻辑的美感( ̄。。 ̄)
什么???你觉得没有,我说有就有。
在这里插入图片描述
所以大家既然都这么觉得,那么我们自然要来领略“TCP诗人”的“握手与挥手” ~~~~

三次握手

关于TCP协议三次握手的讨论应该是面试时经常会被问到的问题,以我的理解来表达一下。首先上图
在这里插入图片描述
正所谓知其然知其所以然,为了确保数据能到达目标,TCP协议采用了三次握手(three-way handshaking)策略。用TCP协议把数据包送出去后,TCP不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志——SYN(同步序列编号)和ACK(确认字符)、Seq(序列号)。Seq就是英文本来的意思顺序、初始序号。那么SYN和ACK又是什么呢?下面我们来一 一介绍:

SYN

SYN:同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

SYN攻击
在黑客攻击事件中,SYN攻击是最常见又最容易被利用的一种攻击手法。
SYN攻击属于DDoS攻击的一种。因为SYN消息是TCP连接的第一个、非常小的一个数据包。所以SYN 攻击利用TCP协议缺陷,通过大量此类的包发送大量的半连接请求,由于这些包看上去来自实际不存在的站点,因此无法有效进行处理。每个机器的欺骗包都要花几秒钟进行尝试方可放弃提供正常响应,耗费了CPU和内存资源。

SYN攻击除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上SYN攻击并不管目标是什么系统,只要这些系统打开TCP服务就可以实施。

ACK

ACK (Acknowledge character)即是确认字符,表示接收到的字符无错误。在数据通信中,接收站发给发送站的一种传输类控制字符,表示发来的数据已确认接收无误。
在TCP/IP协议中,如果接收方成功的接收到数据,那么会回复一个ACK数据。通常ACK信号有自己固定的格式,长度大小,由接收方回复给发送方。其格式取决于采取的网络协议。

在这里插入图片描述
三次握手的详细过程如上图所示:

第一次握手:建立连接时,客户端首先发送一个带SYN标志的数据包给(seq=a)服务器,并进入SYN_SENT状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=a+1),同时自己也发送一个SYN包(seq=b),即SYN+ACK包以示传达确认信息。,此时服务器进入SYN_RECV状态。

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=b+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

SYN和ACK标记是双方通信对暗号的过程,seq表示己方收到数据截止到seq,期望下次收到对方发送的以ack即seq+1开始的数据,
若在握手过程中某个阶段莫名中断,TCP协议会再次以相同的顺序发送相同的数据包。

为什么不是两次握手?

原因是为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。例如我们在发送过程中,假如是两次握手的话:当客户端给服务器发送一个连接请求,因为网络的原因该请求没有按时到达,客户端就会重新发送一次请求,这次请求正常到,然后服务器就会给客户端一个确认请求,此时就可以传送数据了。但是当客户端第一次发送的数据又来到了(客户端以为这个包已经丢失了),那么服务器就会再次向客户端发送一个确认,此时的客户端就不知道这个确认的意义了,而服务器就会在一直等待着客户端给他发送信息(如果这样的次数很多就会导致资源浪费),所以说不应该使用“两次握手”。

四次挥手

TCP采用“四次挥手”来断开连接
致于采用“四次挥手”的原因是由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

FIN

可能有小伙伴不了解FIN是什么,在这做简单介绍,FIN为TCP报头的码位字段,该位置为1的含义为发送方字节流结束,用于关闭连接。
当两端交换带有FIN标志的TCP报文段并且每一端都确认另一端发送的FIN包时,TCP连接将会关闭。FIN位字面上的意思是连接一方再也没有更多新的数据发送。然而,那些重传的数据会被传送,直到接收端确认所有的信息。

当然
在这里插入图片描述
四次挥手过程看似复杂,其实容易理解。与三次握手相比将SYN换成了FIN
在这里插入图片描述
四次挥手的详细过程如上图所示:
第一次挥手:客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。

第二次挥手:服务器B收到FIN后,发送一个ACK给客户端A,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务器B进入CLOSE_WAIT状态。

第三次挥手:服务器B发送一个FIN,用来关闭服务器B到客户端A的数据传送,服务器B进入LAST_ACK状态。

第四次挥手:客户端A收到FIN后,客户端A进入TIME_WAIT状态,接着发送一个ACK给服务器B,确认序号为收到序号+1,服务器B进入CLOSE状态,客户端A等待2*MSL时间后进入CLOSE状态,完成四次挥手。

为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

为什么客户端要等待2MSL后关闭?

一、确保有足够的时候让对方收到ACK包,如果被动关闭的那一方没有收到ACK包,就会触发被动关闭的端重发FIN包,一来一去所用的时间就是2MSL。
二、同时也可以避免新旧连接混淆。因为有的路由器会缓存ip数据包,如果连接被重用了,那么这些延迟收到的包就可能会跟新的连接混在一起。

猜你喜欢

转载自blog.csdn.net/weixin_45797022/article/details/106330271