TCP的三次握手和四次挥手(清晰易懂)
首先,来看下TCP的协议段格式 :
我们特别要注意的是其中的保留位:
- URG: 紧急指针是否有效
- ACK: 确认号是否有效
- PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
- RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
- SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
- FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
接下来我们看TCP的三次握手:
TCP在建立连接时,需要双方同步一下信息,从而能够建立连接,下图是建立连接的过程:
怎么理解呢,看这里:
- 刚才说过SYN是:请求建立连接; 我们把携带SYN标识的称为同步报文段,所以在建立连接的过程中上方都需要向对方发送SYN(SYN=1表示有效)。
- 至于ACK:确认号是否有效;什么意思呢,就是每当一方向另一方发送信息时,对方得给你回应吧:表示收到了信息(这也是TCP可靠的原因之一:确认应答机制),在TCP连接的整个过程中(不管是建立连接、建立好发送数据还是释放连接)只要一方收到对方发来的数据,则就发送ACK表示收到了。
seq是啥呢?就是一个序列号,序列号作用:
- 应答中可以明确应答哪份数据,比如seq=1000,对方收到之后就会回复一个确认序列号ack=1001,表示逆发过来的前1000个数据都收到了;这就是上图中ack为对方发过来的序列号+1的原因;
- 接收方具备了把接收到的数据按照发送时的顺序进行排序的功能——有序交付,很容易想,数据有明确的序列号了,当然可以根据序列号进行排序;
- 具备了去重的能力;根据序列号,如果收到重复数据,直接丢弃。
三次握手理解之后我们再来看四次挥手:
这里我就省略序列号了,理解看这里:
- 首先FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段 ;同样一方在收到另一方发送的FIN时,就会回对方一个ACK,表示我收到了;
- 同样一方发起关闭请求的话另一方也会发起关闭,就是同样向对方发送FIN,而对方收到后也会给ACK确认响应;
状态码相信这样已经很好理解了,那么问题是为什么建立连接三次就够了,而断开连接需要四次呢?看这里:
- 首先三次握手改为四次可以吗,当然可以,只不过三次握手效率更高;
- 那么挥手为什么不能改为三次:
- 在双方开始建立连接时,双方是没有数据的发送接收的,所以一方在接收到另一方发来的连接请求时(SYN),他就会立即把ACK+SYN返回过去,因为没有其他数据的发送,所以不会做其他事情,就会立即返还。
- 而双方在断开连接时(释放连接可以是单方面的),当一方收到另一方发过来的FIN时,会立即返还ACK确认收到,但是它可能还有一些数据没有发送完,所以不会立即关闭,而是等到把当前事情做完,才会发送关闭请求FIN,这就是为什么挥手至少需要四次。
还有一个问题:客户端为什么要等待2MSL才关闭呢:
- MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话
- 就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的); 报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据,
但是这种数据很可能是错误的);- 同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);
对大家有帮助的话还请大家一键三连。