Client ------SYN-----> Server
Client <---ACK/SYN---- Server
Client ------ACK-----> Server

ACK, acknowledge, 美 [əkˈnɑlɪdʒ] v. 承认;认识;确认

SYN, synchronize, 美: ['sɪŋkrə.naɪz] v.(使)同步

handshake 美: ['hæn(d).ʃeɪk] 握手

为什么需要三次握手

其实是4次的

客户端向服务器建立通信需要一来一回, 即两次(请求和回应)

客户端 → 服务器, 服务器 → 客户端

服务器向客户端建立通信也需要一来一回, 这就四次了

服务器 → 客户端, 客户端 → 服务器

服务器向客户端回应时, 可以同时请求, 这就由四次变成了三次

同样的TLS 握手时也可以在客户端回应服务器时同时展开

本来时8次互动, 变成了5次

HTTP/3 甚至把8次合并成了3次

https://networkengineering.stackexchange.com/questions/24068/why-do-we-need-a-3-way-handshake-why-not-just-2-way

TCP 是双向通信

TCP 是会补包的协议

需要互相确定初始序列号

ISN, Initial Sequence Number, 初始序列号

A -> B 我的初始序列号是X
A <- B 我知道了, 我等着接收X++
A <- B 我的初始序列号是Y
A -> B 我知道了, 我等着接收Y++

			TCP A                                                TCP B

  1.  CLOSED                                               LISTEN

  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED

  3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED

  4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>       --> ESTABLISHED

  5.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED

          Basic 3-Way Handshake for Connection Synchronization

			TCP A                                                TCP B

  1.  没有连接的状态                                        监听请求的状态

  2.  发送连接请求 --> <SEQ=100><CTL=SYN>               --> 收到值并+1

  3.  收到值并+1  <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- 确认收到, 发送连接请求
			A 在第二步发送了100, B 返回了101
			A 发送数据的起始序列号就是101

  4.  确认收到    --> <SEQ=101><ACK=301><CTL=ACK>       --> 已连接

  5.  已连接      --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> 已连接
			假设发送数据920字节

  5.  已连接      --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> 已连接

          Basic 3-Way Handshake for Connection Synchronization

为什么初始序列号不统一从0 开始?

https://tools.ietf.org/html/rfc793#section-3.3

预测TCP 序列号的攻击, 使得接收方收到假数据导致真正数据无法处理

https://en.wikipedia.org/wiki/TCP_sequence_prediction_attack

避免与新的连接冲突

连接关闭, 仍有数据在路上没到目的地

新连接建立, 旧数据到达目的地, 序号相同, 造成混乱

初始序列号是随机的, 32个二进制位, 0~4294967295之间的任何值

如何确认数据包有没有丢失

每次发送数据n个字节, 根据数据的大小增加序列号的值

发送方把序列号加上数据的字节数后, 把序列号发过去

发送完所有的数据, 或者一批数据后等待服务器确认相应

比如设定数据大于5000字节就要分批等待确认后再发剩下的

服务器会像握手时那样把序列号+1 后发过来

根据服务器给的序列号继续发送数据

https://www.youtube.com/watch?v=8XJPZttC4RM