TCP 核心问题剖析之 什么 TMD 是 “三次握手”
首先继上文 TCP 协议头全解 我们聊了 TCP 协议头的构成,及其所代表的含义用法。如果你看了我专栏的 网络编程实战 的前几篇文章,相信对于网络的连接请求和传输你已经有了自己的理解。
那么对上文,在 TCP 上所挖的几个坑,将在本文中做一个填补。一件事儿,或者一个知识点,你是否需要事无巨细地理解记忆它呢?能记住当然是好事,但也同样要耗费更多的经历,而在实际的使用中并非所有的点你都需要用到,所以保持核心,保持简单,保持方法论。
本文作为 TCP 的终篇,不会事无巨细地介绍 TCP 的所有细节,而是会对我较为感兴趣的核心点进行理解、讲述和剖析。
本系列将带你学会
- TCP 连接过程为啥是 “三次握手” 而不是 1,2,4,…… N 呢?
- TCP 断开过程为啥是 “四次挥手” 而不是 3 …… N 呢?
- TCP keepalive 是什么?它如何工作?
- TCP 如何保证顺序和不丢包?
- TCP 如何进行流量控制和拥塞控制?
抱歉本来想一文搞定,但发现……,有点长,所以换成系列吧
本文将带你学会
- 什么是握手?nwnmn?
- TCP 连接过程为啥是 “三次握手” 而不是 1,2,4,…… N 呢?
什么是 ”三次握手“?
说实话,对于 TCP 的三次握手,我早有耳闻,甚至可以说是大名鼎鼎、如雷贯耳、不明觉厉、不知所云。
首先说 “握手” ,我可真是谢谢你了,请问 TCP 的手是啥,它握的是啥,谁和谁握,他们握手干嘛?这个比喻可真好,对于懂的人觉得形象,可对于小白的我来说,只能是一脸懵逼。
首先这个握手其实是指代建立链接。
建立链接的本质其实是在想要相互通信的双方的端上,构建一套数据结构算法来收发消息,处理消息,维持状态,是两端的数据沟通与协调。
那所谓的 “三次握手” 其实要做的就是连接发起方确认服务提供方,是否能够正常提供服务 的一个过程。
如果可以那么我们都维护一个约定好的数据结构,进行数据处理,如果不能,那就没什么好谈的了。
所以 三次握手 其实是 确认可进行正常通信的三步发包试探
先来看看哪三步:
- 请求方发送连接请求,TCP 头 标志位 SYN 置为 1,此时 序列号 Seq 为 0 ,确认号 Ack 为 0。
- 服务提供方确认收到, 标志位 SYN 为 1 ,ACK 为 1,此时序列号 Seq 为 0 ,确认号 Ack 为 1。
- 请求方确认收到,标志位 ACK 为 1 ,此时序列号 Seq 为 1 , 确认号 Ack 为 1。此时连接建立完成。
还记得上篇文章说的, 序列号 Seq 和 确认号 Ack 的含义吗?这里简单回顾一下,并解释下为啥握手的时候是这样的。
序列号 Seq 表示在此段报文中数据的第一个字节编号。
确认号 Ack 表示期望收到的下一个报文的 Seq 值,即对应要 确认收到报文的 Seq 值 + 报文数据部分字节总长度。(TCP 协议规定,每段报文发送,都要有应答,这是保证送达的重要规定,即我知道你收到了)
理解了这两个含义,三次握手 的值就很明了了。
- SYN 请求连接,因为是首发,标志位不需要 ACK ,也不需要 确认序号,Seq 为 0
- SYN,ACK,确认 1 报文收到,此时 Seq 为 0 ,确认序号 = 0 + 1 = 1
- ACK 确认 2 收到,此时 Seq = 2.Ack = 1 , Ack = 2.Seq + 1 = 0 + 1 = 1 (注 【2.Ack】 表示报文 2 中 Ack 值)
PS:完了,随便一写 1000 多字了,感觉字数控制不住了,要不要分个几篇?
注意一点,客户端第三步 ACK 时其实就可以发送数据了,此时可以认为连接已经 ok,从理论上第三步握手时就可以携带数据
建立链接为啥握手握三次就好了??
想象一下,这三次握手其实是这样一个场景
客户端 A — 在不? B —> 服务端 B
客户端 A <— A 我在,啥事 — 服务端 B
客户端 A — 太好了你在,我这有些事…… —> 服务端 B
三次握手其实是最简单的一种 确认你在的过程 想想你是不是在聊天中也总这样?(不过大家现在聊天可能更推崇有事说事的 UDP 模式,这个我们后面聊)
能不能 4 次、5 次 、 N 次?
当然能!但是又有什么意义呢?三次握手过后当然也可能对方因为异常而不可达,但是更多的确认并不能让我在纷繁的网络中更多收益,反而平添流程。
所以 三次握手 TCP 做了什么?其实就是 确认你在
一旦 确认你在,之后我就可以说事了,至于说了事之后你处不处理如何处理那是另外的情况,至少在这个情景中,我认为你可以接受听取我的请求了。