TCP三步握手

探索问题:

  1. TCP建立连接为什么要三步握手
  2. 建立连接时发送的SEQ, ACK是什么

三步握手

握手主要原因:在不可靠的网络之上提供可靠的服务。

在Andrew S.Tanenbaum的经典书籍《计算机网络》第5版的「6.2.2 连接建立」小节有很详细的说明:

首先,因为网络有可能会出现延迟或者重复数据包的时候,所以在连接的建立时,每个数据包都会有一个序号,以解决如何区分重复数据包的问题。

然而,这样还是会有问题,《计算机网络》中说的是『数据包的接受者通常不会去保存连接的序号,所以无法区分CONNECTION REQUEST中的初始序号是否和当前连接的序号重复。』我对这句话的理解:

1
2
3
4
5
6
7
8
9
HOST1                      HOST2

| --- SYN(SEQ=x) --> |

| <-- SYN(SEQ=Y) --- |

| --- SYN(SEQ=x, ACK=y+1) --> |

| <-- SYN(SEQ=y, ACK=x+1) --- |

此时建立的连接应该是一个,而不是两个,因为所有的连接都是有它们的端点(由TCP的端口加上所在主机的IP地址组成「6.5.4 TCP端的头」小节有介绍)来标识的。第一个请求产生了一个由(x,y)标识的连接,而第二个请求也建立一个这样的连接,实际上只有一个表项,即(x,y)。

针对上述问题,引入了三步握手协议。这个协议要求在建立连接时,一方需要和另一方确认连接请求是否是当前的。即 A -SYN(SEQ=x)-> B; B -SYN(SEQ=y, ACK=x+1)->A; A -DATA(SEQ=x+1,ACK=y+1)-> B。

当然三步握手也不是绝对可靠,因为请求只能保证之前的传输是可靠,但不能预测接下来的也正确,在知乎上看到一个回答可以参考TCP 为什么是三次握手,为什么不是两次或四次?, 为了方便阅读,引用至此:

这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足”在不可靠信道上可靠地传输信息”这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.”

字段说明

  1. SEQ,初始序号。在一个时间周期T(互联网比较随意的定为120s,看具体实现)内,这个序号应该是唯一的。

  2. ACK, SEQ+1. 表示确认序号SEQ的请求,TCP确认数据包的机制。

参考

  1. 《计算机网络》 by Andrew S.Tanenbaum
  2. TCP 为什么是三次握手,为什么不是两次或四次?
  3. TCP报文到达确认(ACK)机制