三次握手与四次挥手,你理解了吗?

TCP:面向连接、可靠传输、面向字节流
面向连接:在通信前需要先建立连接,保证双方都具有数据收发的功能
可靠传输:保证数据可以可靠到达对端
面向字节流:可靠的、有序的、双向的,基于连接的一种字节流传输方式

三次握手

在这里插入图片描述
刚开始客户端处于CLOSED状态,服务端处于LISTEN状态
第一次握手:客户端向服务端发送一个SYN报文,并且指明客户端的初始序列号ISN,此时客户端处于SYN_SENT状态。(此时SYN=1,初始序列号为seq=x,SYN=1是不能携带数据的,但是需要消耗一个序列号)

第二次握手:服务端接收到客户端的SYN报文后,要客户端的序列号ISN+1作为ACK的值响应客户端的SYN,表示已经收到客户端发送的SYN报文,但是服务端为了确保客户端具有接受数据的能力,也会向客户端发送一个SYN报文,此时服务端处于SYN_RCVD状态。(此时SYN=1,ACK=1,初始化序列号seq=y, 确认号ack= x+1)

第三次握手:客户端接收到服务端的SYN报文,会向服务端发送一个以ISN+1作为ACK的值的ACK报文,此时客户端处于ESTABLISHED状态,当服务端接收到客户端的ACK报文后,也处于ESTABLISHED状态,表示已经建立连接,可以进行通信。(ACK=1,初始化序列号seq=x+1,确认号ack=y+1)

(1)为什么要进行三次握手,两次不可以吗
因为TCP是全双工通信,所以要确保两端都具有数据收发的能力。
假设客户端发送一个SYN包后直接退出,若只建立两次连接,服务端发送的数据就会丢失,因此服务端在发送数据的时候也要确保对方在线,所以不仅要回应客户端的SYN包而发送一个ACK包,还要发送一个SYN请求,确保对方也具有收发数据的能力 ,由于SYN和ACK可以同时发送,所以建立四次连接没有必要。

第一次握手:客户端什么都不能确认,服务端可以确认对方发送正常
第二次握手:客户端可以确认自己具有收发数据的能力,对方也有收发数据的能力,而服务端只能确认自己接收正常,对方发送正常,但是不能确认对方接收正常和 自己发送正常;
第三次握手:客户端可以确认自己和对方都具有收发数据的能力,服务端也可以确认自己和对方都具有收发数据的能力。
所以三次握手是为了保证双方都具有收发数据的能力,两次不安全,四次没必要。

(2)如果三次握手失败,服务端会如何处理
①客户端发送的SYN没有到达服务端:此时服务端并不知道这个请求,所以不做任何处理
②客户端发送了SYN后,服务端收到并且进行了SYN+ACK响应,但是没有收到ACK响应:服务端等待最后一个ACK超时后,会给客户端发送一个RST重置连接报文,要求对方重新建立连接,释放当前新建的这个套接字,这样做的目的是为了方式SYN泛洪攻击。

(3)如果已经建立了连接,但是客户端突然出现了故障怎么办
TCP设有一个保活计时器,当客户端出现故障时,服务器不会一直等待,浪费资源。服务端每收到一次客户端的请求都会重新复位这个计时器(时间通常设置为两个小时),若超过设置时间,还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75s发送一次,若连续发送10次后都没有回应,则认为客户端出现故障,然后就会关闭连接。

(4)什么是半连接队列
当服务端第一次接收到客户端的SYN报文后,处于SYN_RCVD状态,还没有完全建立连接,服务器会把这种状态下的连接请求放在一个队列中,称为半连接队列。

当客户端与服务端完成三次握手,完全建立连接后,就会把这些建立起来的连接放到一个队列中,称为全连接队列。

(5)三次握手中可以携带数据吗?
在三次握手的过程中,前两次握手是不可以携带数据的,但是第三次握手可以携带数据。

第一次不能携带数据是防止恶意攻击服务器,在第一次握手的时候无法确认服务器的收发数据的能力,但是攻击者不会理会服务器是否能接受数据,如果能携带数据,攻击者向服务器发送大量的SYN报文,服务器就要花费大量的时间和空间来处理这些数据,所以第一次握手不能携带数据就是防止恶意攻击。
第三次握手客户端向服务端发送ACK报文时已经确认服务端具有收发数据的能力,所以携带数据也是没有问题的。

(6)什么是SYN泛洪攻击?
SYN泛洪攻击就是攻击者向目标主机发送大量的SYN连接请求,服务器会创建大量的socket,并且回复SYN+ACK,会产生大量的半连接socket,造成资源浪费,如果半连接队列满了会造成正常的连接无法建立。

解决办法:
①缩短syn timeout(服务器发送SYN后等待ACK回复的超时等待时间)
②采用syn cookie短时间那个IP重复就加入黑名单。
③增大半连接数

四次挥手

在这里插入图片描述
客户端与服务端开始的时候都处于ESTABLISHED状态,假设是由客户端主动关闭。

第一次挥手:客户端向服务端发送一个FIN包,表示不再发送数据,但是还可以接收数据,此时客户端处于FIN_WAIT1状态(此时FIN=1,seq=u),等待服务端响应

第二次挥手:服务端接收到客户端的FIN包,会发送一个ACK确认报文,客户端的序列号+1作为ACK的值,此时的服务端处于CLOSE_WAIT状态,TCP处于半关闭状态,客户端收到服务端发送的确认后,会进入FIN_WAIT2状态,等待服务端发起TCP断开请求(此时ACK=1,seq=v,ack=u+1)

第三次挥手:当服务端想要断开连接请求就会像第一次挥手一样,向客户端发送一个FIN包,并且会指定一个序列号,此时服务端处于LAST_ACK状态,等到客户端的确认回复(此时FIN=1,seq=w,ack=u+1)

第四次挥手:当客户端接收到服务端的FIN包,就会进行确认回复发送一个ACK报文,此时客户端进入TIME_WAIT状态,当服务端接收到客户端的ACK报文后,进入CLOSED状态,表示TCPL连接已经断开。(此时ACK=1,seq=u+1,ack=w+1)

(1)挥手为什么是四次,而不是三次
主动关闭方发送FIN包后表示不再发送数据,但是还有可能是要接收数据,因此接收到FIN包后不能直接断开,接收到FIN包的这一端有可能还要继续发送数据,所以ACK和FIN不能同时发送,只有这一端确定不再发送数据,才会给对方发送一个FIN包,所以挥手进行三次不能将TCP连接完全断开。

(2)FIN包发送方为什么发送最后一个ACK后不直接进入CLOSED状态,而是进入TIME_WAIT状态,等待一段时间呢?
假如没有TIME_WAIT状态,直接进入CLOSED状态释放资源,可能会造成危险。
客户端发送ACK后,若这个ACK包丢失,服务端接收不到ACK,则会重传一个FIN包
①若客户端又立即以相同的地址启动客户端,此时客户端没有任何操作就会接收到一个FIN包,会对新连接造成影响;
②若客户端有立即以相同的地址启动客户端,并且向服务端发送一个SYN请求,而服务端此时还处于LAST_ACK状态,收到SYN请求后会认为状态错误,会向客户端发送一个RST重置连接报文,要求对方重新建立连接;
因此主动关闭方在发送最后一个ACK后会等待一段时间,处理有可能重传的FIN包。

(3)为什么TIME_WAIT需要的时间是2MSL?
MSL是TCP报文的最大生存周期,因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文都已经消失;同时也可以保证最后一个报文可靠到达(接收有可能重传的FIN包)

(4)服务器出现大量的CLOSE_WAIT是什么原因?
CLOSE_WAIT是收到FIN包进行响应后的状态,等待调用close/shutdown,出现大量的CLOSE_WAIT表示程序中有大量的套接字断开后没有调用close/shutdown进行释放资源,是代码中的操作。

(5)出现大量的TIME_WAIT的原因?
TIME_WAIT是主动关闭,释放资源,发送最后一个ACK进入的状态,若出现大量的TIME_WAIT则意味着服务器上出现大量主动的关闭连接,通常出现在爬虫服务器,可以开启地址重用,设置MSL时间。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值