学习记录来源:《32个Java面试必考点》
三次握手建连过程:
- 首先在建立连接前需要让Server端先监听端口。因此,Server端建立连接前的初始状态是listen状态
- 这时Client端准备建立连接,先发送一个SYN同步包,发送完同步包后,Client端的连接状态为syn_sent状态
- Server端收到SYN后,同意建立连接,会向Client端回复一个ACK,由于TCP是双工传输,Server端也会向Client端同时发送一个同步请求SYN,申请Server端向Client端建立连接。发送完ACK和SYN后,Server端的状态就变成了syn_rcvd(syn_received)
- Clinet收到Server的ACK后,Client的连接状态就变成了established的状态。同时,Client端向Server端发送ACK响应,回复Server端的SYN请求。
- Server端收到Client端的ACK后Server端的连接状态就变成了established的状态。
此时,建连完成,双方随时进行数据传输。
- 三次握手是为了建立双向连接
- 需要记住Client端和Server端的连接状态变化
- 回答SYN洪水冲击发生的原因:Server端在收到Client端的SYN请求后,发送了ACK和SYN,但是Client端不进行回复,导致Server端大量的连接处在syn_rcvd状态,进而影响其它正常请求的建连
- 上面解决:可以设置Linux的TCP参数,syc_ack_retries=0来加快半连接的回收速度.或者调大max_syn_backlog来应对少量的SYN洪水攻击。
四次挥手断连过程:
- 首先通信的双方(Server和Client)起初都是established的状态
- 然后Client端先发起了关闭链接请求。Client端向Server端发起了一个FIN包,表示Clinet端已经没有数据要发送了,然后Client端就进入了fin_wait_1状态。
- Server端收到FIN后,返回ACK。然后进入close_wait状态,此时,Server处于半关闭状态。因为此时Client向Server方向已经不会发起数据了,但是Server向Client可能还有数据要发送。当Server端数据发送完毕后,Server端会向Client端发送FIN,表示Server端也没有数据要发送了,这时,Server进入last_ack阶段,就等待Clinet端的应答就可以关闭连接了。
- Client端收到Server端的FIN后,回复ACK,然后进入time_wait状态。time_wait状态下,需要等待两倍的MSL,就是最大报文段生存时间,来保证连接的可靠关闭,之后才会进入到closed状态
- 而Server端在收到ACK后就直接可以进入到closed状态。
- 为什么要等待两倍的MSL之后才能关闭连接?
原因有2个:
1.要保证TCP协议的全双工连接能够可靠关闭
2.要保证这次连接中重复的数据段能够从网络中消失,防止端口被重用的时候,可能会产生数据混淆 - 大量Socket处于time_wait或者close_wait状态的问题?
一般开启Linux的TCP参数tw_reuse和tw_recycle能够加快time_wait的回收
而出现在量的close_wait状态,一般是被动关闭的一方,可能存在代码的bug,没有正确关闭连接所导致的