TCP头部(必看)
了解TCP头部,对理解TCP连接过程非常重要!!
重点介绍几个字段;
- Seq:Sequence Number序号,用来标记数据包,通常是随机值;
- Ack:Acknowledge Number确认序号,Ack = Seq + 1;
- 标志位
- SYN:建立一个连接
- ACK:确认序号有效
- FIN:断开一个连接
- RST:连接异常,需要断开连接
三次握手
通过三次握手,来确认双方的收发能力,以服务A请求与服务B建立连接为例;
- 初始状态A为CLOSED,B为LISTEN;
- A给B发送报文,设置SYN标志位,附带Seq序列号,并更新状态为SYN-SENT;
- B收到并回答,设置SYN和ACK标志位,并附带自己的Seq序号和Ack确认序号,更新状态为SYN-RCVD;
- A收到并回答,设置ACK标志位,附带Ack确认序列号,并更新状态为ESTABLISHED;
- B收到后更新状态为ESTABLISHED;
为什么需要三次
- 第一次握手确认A的发送能力和B的接收能力;
- 第二次握手确认B的收发能力和A的收发能力;
- 第三次握手确认A的接收能力和B的发送能力;
结论:只有三次握手双方才能确认收发能力。
四次挥手
- A发起报文请求断开连接,设置FIN标志位,附带Seq序号,并更新状态为FIN_WAIT_1;
- B收到后并回答,设置ACK标志位,附带Ack确认序号和Seq序号,并更新状态为CLOSE_WAIT;
- A收到后更新状态为FIN_WAIT_2;
- B在传输完所有数据后,设置FIN和ACK标志位,并附带Seq序号和Ack确认序号,更新状态为LAST_ACK;
- A收到后并回答,设置ACK标志位,附带Ack确认序号和Seq序号,等待2MSL后自动断开连接,更新状态为CLOSED;
- B收到后更新状态为CLOSED;
挥手为什么需要四次
- A发送FIN表示后续不会发送数据,但能接收;
- B接收到FIN可能还有数据需要发送,处理完才能给A回复FIN;
为什么需要TIME_WAIT
- 确保A的ACK能到达B,2MSL刚好是报文一个来回的时间;
- 防止“已失效的连接请求报文段”出现在本连接中;
MSL,Maximum Segment Lifetime,报文最大生存时间。
TIME_WAIT过多的问题
- 内存资源占用,连接会占一个文件描述符;
- 端口占用,服务器端口资源有限;
可以通过重用SOCKET和加速TIME_WAIT的SOCKET回收避免上述异常。