TCP三次握手四次挥手详解
三次握手
刚开始客户端处于 closed (关闭)的状态,服务端处于listen状态
1.第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(C)。此时客户端处于SYN_Send(发送)状态。
2.第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(S),同时会把客户端的ISN(C+1)作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_RCVD(半连接)的状态。
3、第三次握手:客户端收到SYN报文之后,会发送一个ACK报文;当然,也是一样把服务器的 ISN(S+1)作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 establised(建立连接)状态。
四次挥手
刚开始双方都处于establised状态,假如是客户端先发起关闭请求,则:
1、第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1(先前中断请求的确认/等待服务器tcp连接中断请求确认)状态。
2、第二次挥手:服务端收到FIN之后,会发送ACK报文,且把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到客户端的报文了,此时服务端处于CLOSE_WAIT(等待客户端发来连接中断请求)状态。
3、第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给FIN报文,且指定一个序列号。此时服务端处于LAST_ACK(等待原来发向远程TCP连接中断请求确认)的状态。
4、第四次挥手:客户端收到 FIN 之后,一样发送一个ACK报文作为应答,且把服务端的序列号值+1 作为自己ACK报文的序列号值,此时客户端处于TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入CLOSED(没有任何连接)状态
5、服务端收到ACK报文之后,就处于关闭连接了,处于CLOSED状态。
要确保服务器是否已经收到了我们的 ACK 报文,如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。
SYN:同步连接序号 ACK:请求/应答 0/1 FIN:结束连线 0位请求/1为结束 RST:连线复位,断开重连 PSH:通知协议栈将TCP数据交给上层程序处理
三次握手的作用:
1、确认双方的接受能力、发送能力是否正常。
2、指定自己的初始化序列号,为后面的可靠传送做准备。
ISN序列号是固定的吗?
三次握手的一个重要功能是客户端和服务端交换ISN序列号(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。
如果ISN是固定的,攻击者很容易猜出后续的确认号,因此ISN是动态生成的。
什么是半连接队列?
服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s, 2s, 4s, 8s
三次握手过程中可以携带数据吗
很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的;第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
为什么这样呢?
大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的SYN报文中存放大量的数据,然后疯狂着重复发SYN报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。也就是说,第一次握手可以放数据的话,是会让服务器更加容易受到DOS攻击。
而对于第三次的话,此时客户端已经处于established状态,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据进行传输。
按惯例,我们配张图片
|