HTTP三次握手和四次挥手

三次握手

三次握手是指客户端在和服务端建立tcp连接的时候需要进行三次通信,然后才能完成连接。

image

这三次通信分别是:

  1. 客户端向服务端发送一个数据包,告诉服务端需要建立连接;
  2. 服务端收到客户端发送的数据包之后,会返回一个数据包,通知客户端,我已经收到你的连接请求;
  3. 客户端收到服务端返回的信息后,知道服务端已经准备好建立连接,但是还需要再发送一个数据包给服务端,用于告诉服务端我已经收到你的回复了。

这个时候,连接就已经建立了。双方可以进行数据传输了。

为什么一定需要三次连接呢?

主要还是因为存在数据可能丢失的问题,也就是说不管是客户端或者服务端,都不能确定自己发出的信息对方有没有正常接收到,所以需要对方发送一个回复信息。用于确定自己发出的信息已经被对方正常接收。

双方是如何确认对方的呢?

比如服务端可能会同时接收多个客户端的连接请求,它是如何区分不同客户端的呢?答案就是随机值。

客户端在第一次握手的时候,会生成一个随机数(j),和数据包一起发送给服务端;

第二次握手的时候,服务端会将这个随机值+1(j+1),同时服务端也生成一个随机值(k)一起再返回给客户端;

第三次握手的时候,客户端会检验j+1的值,如果检验通过,会将k+1,然后发送给服务端,服务端检验k+1的值,检验通过以后,连接就建立了。

当然,实际的tcp连接中,数据包不只是包含随机值,同时还有各种标志位用于确认请求。

SYN攻击

在三次握手过程中,当服务端发送SYN-ACK之后收到客户端的ACK之前的状态称为半连接状态,如果服务端一直没有收到客户端的ACK包,服务端需要不断重发直到超时。SYN攻击就是客户端在短时间内大量伪造不存在的ip地址,向服务端发起连接请求,由于源地址不存在,服务端一直不能收到客户端返回的ACK包,导致网络堵塞甚至系统瘫痪。SYN攻击是一种典型的DDOS攻击,如果服务端有大量半连接状态且源ip地址是随机的,则可以判断遭到SYN攻击。可以使用:

#netstat -nap | grep SYN_RECV

四次挥手

四次挥手是指断开TCP连接时,需要客户端和服务端总共发送4次数据包以确认连接的断开

image.png

由于TCP连接是全双工的,因此,每个方向都需要单独进行关闭。这一原则是指当一方完成数据传输任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只意味着这一方向上没有数据传输,但在这个TCP连接上仍然能够发送数据,直到这一方向也发送FIN来。

首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

  1. 第一次挥手:client发送一个FIN,用来关闭client到server的数据传输,client进入FIN_WAIT_1状态;
  2. 第二次挥手:server收到FIN后,发送一个ACK给client,确认序号为收到序号+1,server进入CLOSE_WAIT状态;
  3. 第三次挥手:server发送一个FIN,用来关闭server到client的数据传输,server进入LAST_ACK状态;
  4. 第四次挥手:client收到FIN后,client进入TIME_WAIT状态,接着发送一个ACK给server,确认序号为收到序号+1,server进入CLOSE状态。

完成四次挥手。

为什么关闭连接需要四次挥手呢?

这是因为当收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是还能接收数据。己方也未必全部将数据都发送给对方了,所以己方可以立即CLOSE,也可以发送一个数据给对方后,再发送FIN报文给对方表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

原因有二:

  1. 保证TCP协议的全双工连接能够可靠关闭;
  2. 保证这次连接的重复数据段从网络中消失。

先说第一点,如果client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致server没有收到client最后回复的ACK。那么server就会在超时之后继续发送FIN,此时由于client已经CLOSED了,就找不到与重发的FIN对应的连接,最后server就会收到RST而不是ACK,server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

再说第二点,如果client直接CLOSED,然后又再向server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

你可能感兴趣的:(HTTP三次握手和四次挥手)