面试常客:三次握手,四次挥手

三次握手四次挥手:

刚开始客户端处于Closed状态,服务器处于Listen状态。

第一次握手:客户端给服务端发一个SYN报文,并指明客户端的初始化序列号ISN。此时客户端处于SYN_SENT状态。 首部的同步位SYN=1,初始序号seq=x,SYN的报文段不能携带数据,但要消耗掉一个序号。

第二次握手:服务器收到客户端的SYN报文后,会以自己的SYN报文作为应答,并且也指明了自己的初始化序列号ISN(s)。同时会把客户端的ISN+1作为ACK的值,表示自己已经收到了客户端的SYN,此时服务器处于SYN_RCVD的状态。 在确认报文段中SYN=1,ACK=1,确认号 ack=x+1,初始序号seq=y。

第三次握手:客户端收到SYN报文后,会发送一个ACK报文,也是把服务器的ISN+1作为ACK的值,表示已经收到了服务端的SYN报文,此时客户端处于ESTABLISHED状态。服务器收到ACK报文后,也处于ESTABLISHED状态,此时双方已建立起了连接。 确认报文段ACK=1,确认号ack =y+1,序号seq=x+1,ACK报文段可以携带数据,不携带数据则不消耗序号。


发送第一个SYN的一端将执行主动打开,接收这个SYN并发回下一个SYN的另一端执行被动打开。

在socket编程中,客户端执行connect()时,将触发三次握手。

为什么需要三次握手,两次不行吗?

第一次握手:客户端发送网络包,服务端收到了。

这样服务器就能得出结论:客户端的发送能力、服务端的接受能力是正常的。

第二次握手:服务端发送网络包,客户端收到了。

这样客户端就能得出结论:服务器的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认自己的发送能力以及客户端的接收能力是否正常。

第三次握手:客户端发送网络包,服务端接收到了。

这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常的,此时双方都确认无误,连接建立成功。

什么是半连接队列?

服务器第一次收到客户端的SYN之后,就会处于SYN_RCVD状态,此时双方还没有完全建立起连接,服务器会把此种状态下的请求连接放在一个队列里,这种队列称之为半连接队列。

还有全连接队列就是已完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

SYN-ACK重传问题

服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。

注意:每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为1s,2s,4s,8s…

ISN(Initial Sequence Number)是固定的吗?

当一端为建立连接而发送他的SYN时,他为连接选择一个初始序号。ISN随时间变化而变化,因此每个连接都将具有不同的ISN。ISN可以看做一个32比特的计数器,每4ms加1。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。

三次握手的其中一个重要功能是客户端和服务端交换ISN,以方便让对方知道接下来接收数据的时候如何按序列号组装数据。如果ISN是固定的,攻击者很容易猜出后续的确认号,因此ISN是动态生成的。

三次握手过程中可以携带数据吗?

第三次握手的时候是可以携带数据的,但是,第一次第二次握手不可以携带数据。

第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易收到攻击了。而对于第三次的话,此时客户端已经处于ESTABLISHED状态。对于客户端来说,他已经建立起了连接,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据。

SYN攻击是什么?

服务器端的资源分配是在二次握手时分配的,而客户端的资源是在三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用半连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN攻击是一种典型的DoS/DDoS攻击。

TCP协议如何保证可靠传输?

1.应用数据被分割成TCP认为最合适发送的数据块

2.TCP发送给的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层

3.校验和:TCP将保持它首部和数据的校验和;这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化,如果收到段的校验和有差错,TCP将丢弃这个报文段且不确认收到此报文段

4.TCP的接收端会丢弃重复的数据

5.流量控制:TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP使用的流量控制协议是可变大小的滑动窗口协议

6.拥塞控制:当网络拥塞时,减少数据的发送

7.停止等待协议:也是为了实现可靠传输的,基本原理是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组

8.超时重传:当TCP发出一个段后,他启动一个定时器,等待目的端确认收到这个报文后,如果不能及时收到一个确认,将重发这个报文段


第一次挥手:客户端发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。

即发出连接释放请求报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1状态,等待服务器确认。

第二次挥手:服务器收到FIN之后,会发送ACK报文,且把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到客户端的报文了,此时服务器处于CLOSE_WAIT状态。

即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT状态,此时TCP处于半关闭状态,客户端收到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2状态,等待服务端发出的连接释放报文段。

第三次挥手:如果服务端也想断开连接,和客户端第一次挥手一样,发送FIN报文,且指定一个序列号。此时服务端处于LAST_ACK的状态。

即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务器进入LAST_ACK状态,等待客户端确认。

第四次挥手:客户端收到FIN后,一样发送一个ACK报文作为应答,且把服务端的序列号+1作为自己ACK报文的序列号值,此时客户端处于TIME_WAIT状态。需要过一阵子以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文后,就处于CLOSED状态。

即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。


挥手为什么需要四次?

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

2MSL等待状态

TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL,他是任何报文段被丢弃前在网络内的最长时间。这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。

对一个具体是实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN).

这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能被使用。

四次挥手连接释放时,等待2MSL的意义?

为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

两个理由:

1.保证客户端发送的最后一个ACK报文段能够到达服务器

这个ACK报文段有可能丢失,使得处于LAST-ACK状态的服务器收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。

2.防止“已失效的连接请求报文段”出现在本连接中

客户端在发送完最后一个ACK报文段后,在经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?

理论上,四个报文都发送完毕,就可以直接进入CLOSE状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值