在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。
三次握手
三次握手(建立连接):本质上是双方保存了一个连接状态。
①客户端发送SYN:申请建立客户端到服务端的连接
②服务端返回SYN+ACK:申请建立服务端到客户端的连接
其中ACK是对第一个数据报的应答,SYN和ACK可以合并一起发送,也可以分开发(一个数据报,两个标志位置为1)
③客户端返回ACK:对第二个数据报SYN的应答
四次挥手
四次挥手(断开连接):
①客户端发送FIN到服务端:申请关闭客户端到服务端的连接
②服务端返回ACK → 服务端状态置为CLOSE_WAIT
③服务端发送FIN到客户端:申请关闭服务端到客户端的连接 → 客户端接收到,状态置为TIME_WAIT
④客户端返回ACK → 服务端状态置为CLOSED(已关闭)
→ 客户端等待一定时间,状态置为CLOSED(已关闭)
细节问题(四次挥手)
1. 双方的连接状态,为什么最后才是CLOSED(已关闭)?
双方都要保证可靠的关闭连接。如果一边关闭,一边还存在,就属于藕断丝连,也就是半关闭状态。
客户端接收到第3个数据报(服务端发送FIN到客户端),不能马上置为CLOSED。因为第4个数据报(客户端返回ACK)可能出现丢包,服务端就会根据超时重传机制重发第3个数据报,此时客户端如果是CLOSED,就无法接收。
2. 第2、3个数据报为什么没有合并发送?
第2个数据报,是系统内核返回的,不需要程序写代码来发送。
第3个数据报,是程序调用CLOSED方法发送的(服务端在关闭连接前,可能需要做一些其他工作)。
拓展:第2,3个数据报是否可以合并?
第2个数据报先放到缓冲区(可能是立即发,也可能不是),再把第3个数据报也发送到缓冲区。此时,如果第2个数据报还在缓冲区,就可能合并发送。
3. 服务端如果出现大量的CLOSE_WAIT状态,是为什么?
服务端没有执行CLOSE方法(因为执行CLOSE才会发送第3个数据报)。
4. 客户端接收第3个数据报,状态是TIME_WAIT,需要等待多久?
2msl。
1msl是单个报文传输的最大时间,需要等待的就是第4次返回,及第3次可能的重传数据。