【我的区块链之路】- 说一说TCP的3次握手和4次挥手

【转载请标明出处】https://blog.csdn.net/qq_25870633/article/details/82729960

废话不逼逼直接上主题,我们再说TCP的三次握手之前先来了解下几个概念:

(1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记
(2)确认号:ack序号,占32位,只有ACK标志位为1时,确认号字段才有效,ack = seq+1
(3)标志位:共6个,即 URG、ACK、PSH、RST、SYN、FIN 等,具体含义如下:
       (A)URG:紧急指针(urgent pointer)有效。为1,表示某一位需要被优先处理
       (B)ACK:确认序号有效。一般置为1
       (C)PSH:接收方应该尽快将这个报文交给应用层。提示接收端应用程序立即从TCP缓冲区把数据读走
       (D)RST:重置连接。对方要求重新建立连接,复位
       (E)SYN:发起一个新连接。
       (F)
FIN:释放一个连接。
需要注意的是:
(A)不要将确认序号ack与标志位中的ACK搞混了
(B)确认方 ack = 发起方 seq + 1,两端配对。 

3次握手过程详解


所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:

 

(1)第一次握手:
Client将 标志位SYN置为1随机产生一个值 seq = J <32位>,并将该数据包发送给Server,Client进入 SYN_SENT状态,等待Server确认。

(2)第二次握手:
Server收到数据包后 由标志位SYN=1 知道Client请求建立连接,Server将 标志位 SYN 和 ACK 都置为1, ack = J+1,随机产生一个值 seq= k,并将该数据包发送给Client以确认连接请求,Server进入 SYN_RCVD状态

(3)第三次握手:
Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确时则将标志位ACK置为1,ack= k+1,并将该数据包发送给Server,Server检查ack是否为 k+1,ACK是否为1,如果正确则连接建立成功,ClientServer进入 ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

很简单,其实就是用 两个标识位 SYN ACK 及 两个序号值  seq ack 来做请求确认等动作

【可能存在的问题】:

 SYN攻击

在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect)【及第二和第三次之间】,此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击 就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击是一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:

# netstat -nap | grep SYN_RECV

好了以上就是所谓的TCP三次握手的原理,其实也没什么难的;下面我们来说一说TCP的四次挥手:

4次握手过程详解:

所谓的四次挥手就是终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开

这一过程由客户端或服务端任一方执行close来触发

如图:

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接收到一个FIN只是意味着这一方向 <及FIN的发起方不会发送数据给 FIN接收方了>上没有数据流动了,即不会再收到数据了但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

(1)第一次挥手
Client发送一个FIN = 1,seq=u,用来关闭Client到Server的数据传送,Client进入 FIN_WAIT_1状态。这表明client已经没有数据要发送了,并要求释放链接。

(2)第二次挥手:
Server收到FIN后,返回确认信息。ACK = 1,seq = v,ack = u+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。这个时候,客户端不能给服务器发送信息报文,只能接收。但是服务器要是还有信息要传给服务器,仍然能传送。同时 Client接收到回应是进入  FIN_WAIT_2状态

(3)第三次挥手:
当服务器也没有了可以传的信息之后,给客户端发送请求结束的报文。Server发送 FIN = 1,ACK = 1,ack = u+1,seq = w

用来关闭Server到Client的数据传送,Server进入 LAST_ACK状态

(4)第四次挥手:
Client收到FIN后,返回确认报文,ACK = 1,seq = u+1,ack = w+1 给Server ,发送完毕之后,Client进入 TIME_WAIT状态,并等待两个时间周期后Client 进入 CLOSED状态。而Server,接收到,Server进入 CLOSED状态,完成四次挥手。

为什么最后还要等待两个时间周期呢?

1、  客户端的最后发出给Server的ACK报文在传输的时候丢失,服务器并没有接收到这个报文。这个候,服务器就会超时重发这个FIN消息 <因为Server可能会以为Client没收到自己的FIN报文,而在此尝试重发一次>,然后客户端就会重新返回最后一个ACK报文,等待两个时间周期,完成关闭如果不等待这两个时间周期,服务器重发的那条消息就不会收到服务器就因为接收不到客户端的信息而无法正常关闭

2、  预防上一次在三次握手中提到的失效的报文干扰。两个时间周期过去之后,所有的报文都会在网络中消失,保证下一次重新连接的时候有乱七八糟的报文影响。

为什么连接的时候是三次握手,关闭的时候却是四次挥手?

在连接时因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来请求连接的。有我就是说,在请求连接时是需要Client和Server端分别请求和应答的。所以就是,Client 请求连接 SYN -> Server 应答请求 ACK+ 请求连接 SYN -> Client 应答连接 ACK;

在关闭时因为 当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,该报文只是为了应答Client的以表示Server已经接收到了Client发起的 关闭请求 FIN,此时Server 可能还需要传输数据给Client (此时的Client 已经不会在发送数据给Server了,但是还是可以接收 Server 发过来的数据的),然后这时候,在Sever自己处理完所有事情后,才有Server 发起 关闭请求FIN,然后Client 才再次做一次回应,表示收到Server 发来的FIN了,但是由于不敢确认 Server 有没有收到本次回应,所以故意多等 2个时间周期之后在自己关闭自己这一端,(因为在2个周期内,如果由于网络原因,造成Client的回应丢失,那么Server 是会重发 FIN 请求给Client的,这时候Client由于在2个时间周期的等待中,还是会接收到Server 发来的 FIN 的)

好了,以上就是我们所说的TCP连接时的三次握手和TCP断开时的四次挥手。。。

猜你喜欢

转载自blog.csdn.net/qq_25870633/article/details/82729960
今日推荐