三次握手四次挥手

带着问题进行阅读,收获会更大

  • 请画出三次握手和四次挥手的示意图为什么连接的时候是三次握手?

  • 什么是半连接队列?ISN(Initial Sequence Number)是固定的吗?

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

  • 如果第三次握手丢失了,客户端服务端会如何处理?

  • SYN攻击是什么?

  • 挥手为什么需要四次?

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


1. 三次握手

    三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包.主要作用就是为了确认双方的接收能力和发送能力是否正常. 实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息


进行三次握手

第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN©.此时客户端处于 SYN_SEND 状态

    首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号

第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s).同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态.

    在确认报文段中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(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号.

1.png

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

第一次握手确定客户端发送能力,服务端接收能力,第二次握手确定服务端发送能力,客户端接收能力第三次确定双方的接收与发送是否正常


1.2 什么是半连接队列?

服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列. 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传.如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除.一般间隔时间指数增长


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

当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号.ISN随时间而变化,因此每个连接都将具有不同的ISN


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

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


1.5 SYN攻击是什么?

SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪检测 SYN 攻击非常的方便

netstat -n -p TCP | grep SYN_RECV常见的防御 SYN 攻击的方法有如下几种:
  • 缩短超时(SYN Timeout)时间

  • 增加最大半连接数

  • 过滤网关防护

  • SYN cookies技术



2. 四次挥手

    建立一个连接需要三次握手,而终止一个连接要经过四次挥手(也有将四次挥手叫做四次握手的).这由TCP的半关闭(half-close)造成的.所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力


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

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

第二次挥手: 服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放.客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段

第三次挥手: 如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 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状态

2.png

2.1 挥手为什么需要四次?

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


2.2 2MSL等待状态

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


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

MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃


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

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


总结

《TCP/IP详解 卷1:协议》有一张TCP状态变迁图,很具有代表性,有助于大家理解三次握手和四次挥手的状态变化.如下图所示,粗的实线箭头表示正常的客户端状态变迁,粗的虚线箭头表示正常的服务器状态变迁

3.png


发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.5.2 Zero

WX:xcs345525801 QQ:345525801 Tel:19521445850 Email:xcssh868@163.com

Copyright © 2020 许承胜个人博客 版权所有 备案号:皖ICP备18014705号-1