假设A机器是客户端角色,B机器是服务端角色,后者需要前者发起连接请求时先打开某个端口等待数据传输,否则无法正常建立连接。
第一次握手:客户端A发送一个数据包并将SYN同步序号标志位置1,表明希望建立连接。初始序号X,保存在包头的序列号(Sequence Number)字段里。
第二次握手:服务器B收到客户端A的数据包后,通过SYN得知这是一个建立连接的请求,于是发送返回确认包(ACK)应答,并将SYN标志位和ACK标志位均为1。假设这个包中的序列号是y,而且确认序列号ack必须是x+1,表示收到了A发过来的SYN。
第三次握手:客户端A收到B响应包需进行确认, SYN标志位为0, ACK确认序号标志位为1.并且把服务器发来ACK的序号字段+1,即y+1,表示收到了来自服务端B的SYN同步序号。
3 .为什么需要第三次握手?主要有两个目的:信息对等和防止超时
信息对等角度:双方只有确认4类信息(自己收、发报能力、对方收、发报能力),才能建立连接。在第2次握手后,从服务端B视角看还有自己发送报文能力和对方收报能力无法确认。因此在第3次握手后,才确认自己的发报能力和对方的收报能力。
防止超时角度:连接三次握手也是防止出现请求超时导致脏连接
YN超时起因:
Server服务端收到Client客户端的SYN,回复SYN-ACK的时候未收到ACK确认。
Server服务端不断重试直至超时,Linux默认等待63秒才断开连接(默认重试5次1+2+4+8+16+32)。在第5次发出去之后,还需要等待32s才能被判定为超时。
建立连接后,Client出现故障怎么办?
Keep Alive保活机制:
向对方发送保活探测报文(心跳包)检查连接的健康度,如果未收到响应则继续发送。
尝试次数达到保活探测数仍未受到响应则中断。
4 .TCP四次挥手
TCP是全双工通信,双方都能作为数据的发送方和接收方,但TCP连接也会有断开的时候。
第一次挥手:主动关闭方发送一个FIN并进入FIN_WAIT1状态
第二次挥手:被动关闭方接收到主动关闭方发送的FIN并发送ACK,确认序号为收到序号+1,此时被动关闭方进入CLOSE_WAIT状态;主动关闭方收到被动关闭方的ACK后,进入FIN_WAIT2状态
第三次挥手:被动关闭方发送一个FIN并进入LAST_ACK状态
第四次挥手:主动关闭方收到被动关闭方发送的FIN并发送ACK,确认序号为收到序号+1,此时主动关闭方进入TIME_WAIT状态,经过2MSL时间后关闭连接;被动关闭方收到主动关闭方的ACK后,关闭连接
通俗解释:
A机器想要关闭连接,则 带本方数据发送完毕后,传递FIN信号给B机器,此时A机器进行FIN_WAIT1。
B机器应答ACK,告诉A机器可以断开,但是需要等待B机器处理玩数据,再主动给A机器发送FIN信号,此时,A
机器处于半关闭状态(FIN_WAIT2),无法在发送新的数据。
B机器做好连接关闭前的准备工作后,发送FIN给A机器,此时B机器也进入半关闭状态(CLOSE_WAIT).
A机器发送针对B机器FIN的ACK后,进入TIME_WAIT状态,经过2MSL(报文最大生存时间),没有收到B机器传来的报文,则确定B机器已经收到A机器最后发送的ACK指令,此时TCP连接正式释放。
为什么需要四次挥手才能断开连接?
因为是全双工,发送方和接收方都需要FIN报文和ACK报文。
服务器出现大量CLOSE_WAIT状态的原因?
对方关闭socket连接,我方忙于读或写,忙于及时关闭连接。
解决方法:1、检查代码,特别是释放资源的代码。