TCP之三次握手与四次挥手
1. 为什么不是两次握手
对于不了解tcp的人来讲,拿两次握手就足够是可以忽悠住他的,客户端发起一个syn,服务器回复一个synack,两边都确认了对端的收发包是正常的,那为什么还需要第三个ack包呢?一般人可能会回答,万一服务器回复的synack丢失了呢?bingo!是的,但这不是深层次的解答。
2. TCP解决什么问题
TCP全称Transmission Control Protocol,重点是控制,控制什么呢,保证用户发送的所有报文都能送到对端,那怎么做到这一点呢?
上面展示了一般的报文交互流程,即TCP是怎么做到保证报文的不丢失的:
- 如果收到带数据的报文,需要回复ack报文
- 如果收到不带数据的报文,不需要回复ack,但是删除本地之间缓冲的报文
- 如果在一定时间(本文不展开RTO时间)内未收到对端的ACK报文,则重传缓冲区中的报文
而TCP对于带SYN或者FIN标记的报文认为是1个字节,如下抓包,客户端发出的seq序号后两位是04,而对端回复的ack序号后两位是05。
所以更深层次的来理解三次握手原因是因为TCP对于任何带数据的报文都需要回复确认报文,而SYN和FIN报文在TCP看来是1个字节的数据报文。
3. 四次挥手难道三次还不够吗
乍看一下没什么大问题,反正客户端都已经关闭了,为什么TCP不直接回复FIN,表示服务器也关闭呢?
这里涉及到一个非常重要的通信知识,全双工,TCP是支持全双工的一个协议,即支持发包和收包同时进行,同时进行势必带来一个事情是收发包是两个通道,而发出FIN表示的是关闭我方的发送通道,但不代表我方不可以继续收包;收到FIN表示的是关闭我方的接收通道,但不代表我方不可以接续发包。
一般应用程序的设计都是直接调用close系统调用,这种情况三次挥手和四次握手没什么区别。但是还有一个系统调用shutdown,这个接口可以单方面的关闭收或者发通道,所以可以实现下面的场景:
当然后续SERVER再完成业务后还会再调一次shutdown关闭发包通道,客户端在感知到服务器的发包通道关闭时也会再调一次shutdown关闭收包通道。
4. 总结
- 三次握手是TCP必须确认对端发过来的数据。
- 四次握手是因为TCP支持全双工,收发包通道独立的要求。