三次握手:
建立TCP连接,这中间涉及如下几个过程:
Client:close , SYN-SENT, Established
Server:close, Listen, SYN-RECV,Established
1. client向server发送一个SYN包,等待server的确认,
SYN为标识为,表示“我想建立连接”;序号Seq = x(x是随机数);client进入了 SYN-SENT状态
2. server向client返回了一个SYN包,同时结束LISTEN阶段,
标识位为SYN和ACK,代表确认client的Seq有效,server可以正常接受client的数据并且同意建立连接;Seq = y;确认号 Ack = x + 1,是client的序号Seq+1作为自己的Ack,server进入 SYN-RECV阶段
3. client收到SYN、ACK包后,确定了数据传输是正常的,结束SYN-SENT状态,返回ACK包,
ACK代表收到server发来的SYN;Seq = x + 1代表收到了server的Ack,并把它作为自己Seq;确认号Ack = y + 1,表示收到了server的Seq,并加1作为自己的Ack,client进入Established。
当Server收到client发来的报文后,得知server 到 client的传输是正常的,开始Established阶段,完成三次握手。
四次挥手:
为什么服务端易受到 SYN 攻击https://leetcode-cn.com/leetbook/read/networks-interview-highlights/esk4h5/
释放TCP连接。client主动断开,先结束established状态,开始
1. client向server发送报文表示释放连接,
FIN:请求释放连接;Seq = u ;client 进入 FIN-WAIT-1阶段,半关闭状态,停止向server发送通信数据
2. server收到client的FIN报文后,结束established阶段,进入close-wait阶段,返回一个报文,
ACK:表示收到了FIN报文;Seq = v;确认号为Ack = u + 1;server向client的连接准备释放。
client收到了server的ACK以后,进入FIN-WAIT-2阶段
3. server发出ACK报文后,会把没传输完成的数据发送给client,即CLOSE-WAIT,做好了释放的准备,有发送了一段报文,
FIN和ACK:准备好释放连接;Seq = w;Ack = u + 1;结束了CLOSE-WAIT,进入LAST-ACK
4. client收到了FIN和ACK后,确认了server已经准备做好释放连接, 结束了FIN-WAIT-2,进入TIME-WAIT阶段,向server发最后一段报文,
ACK代表收到服务器准备释放连接的信号,
Seq = u + 1 = Ack,确认号Ack = w + 1 。
发送后 client在TIME - WAIT阶段等待2MSL,
server收到后结束LAST-ACK阶段,进入CLOSED。
client等待完2MSL的TIME-WAIT阶段,进入CLOSED。
四次挥手完成。
三次握手中,如果对方没收到信息怎么样?
第一次握手丢失,server不会做任何事,client在等待一段时间后会重新发送SYN报文,若反复发送,反复无回应,超过最大重传次数次数,系统会返回-1。
第二次握手丢失,client会和第一次丢失一样,而服务器会阻塞等待ACK报文。
第三次握手丢失,server会超时重传,超过最大次数以后,自动自动调用accept()返回-1。但是client这时候以为连接成功,向server发送数据,但server不会在监听,就会发送RST报文给client,消除单方面连接。
三次握手的必要性?
目的是让双方都知道彼此的发送和接受为正常,进而进行可靠的通信。若采用了两次握手,server并不知道client的接收是否正常。
在真实环境中,一旦发生丢包,只有两次握手会引起server一直打开端口等待client连接,这会造成巨大浪费。ACK代表已接收,SYN代表server向client建立连接。
四次挥手的重要性?
TCP是全双工的,FIN释放连接和ACK确认接收分别在两次握手中传输。当主动方发出第一个FIN通知时,被动方可能还有没完成的传输,所以会先返回ACK代表收到。
当被动方也没有数据再发送后,就会发送第二个FIN给主动方,最后完全关闭TCP连接。
CLOSE-WAIT的重要性:
server收到了client的FIN报文后,返回了ACK报文并进入了CLOSE-WAIT状态,这个状态是防止server还有未发完的信息。
TIME-WAIT的重要性:
发生在最后一次挥手,client向server发送ACK确认报文,如果client收到FIN后立即关闭A端口,而server并没有关闭A端口,这样的话下次client再用这个端口的话,会收到上次的残留,产生意外。
而且client发送的ACK如果丢失了,有TIME-WAIT会有时间接收server新发的FIN,不然client就会用RST返回给server导致认为有错误发生。但是,如果是高并发的场景下,Time-wait如果回收过慢,会引起大量套接字的积累,需要修改配置或设置so_reuseaddr套接字。
2MSL的计时器(Maximum Segment Lifetime)指一段报文的最大生命周期。
1. 如果server在1MSL内没有收到ACK,再次向client发送FIN,那么client在2MSL内收到了再次发来的FIN,说明server没有收到client上一个发的ACK。client会再次发送ACK给server。
2. 如果client在2MSL内没有收到server再次发送的FIN,说明server成功接受ACK,client即可关闭,完成4次挥手。
因此2MSL的TIME-wait是为了client为了保证server可以收到它的ACK。