TCP 连接的细节问题

2020-09-01 14:34:51 浏览数 (1)

先来描述下三次握手连接:

第一次握手:A 的 TCP 客户端进程也是首先创建传输控制块 TCB。然后,在打算建立 TCP 连接时, 向 B 发出连接请求报文段,这时首部中的同步位 SYN=1,同时选择一个初始序号 seq = x。TCP 规 定,SYN 报文段(即 SYN = 1 的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP 客户进 程进入 SYN-SENT(同步已发送)状态。

第二次握手:B 收到连接请求报文后,如果同意建立连接,则向 A 发送确认。在确认报文段中应把 SYN 位和 ACK 位都置 1,确认号是 ack = x 1,同时也为自己选择一个初始序号 seq = y。请注 意,这个报文段也不能携带数据,但同样要消耗掉一个序号 。这时 TCP 服务端进程进入 SYNRCVD(同步收到)状态。

第三次握手:TCP 客户进程收到 B 的确认后,还要向 B 给出确认。确认报文段的 ACK 置 1,确认号 ack = y 1,而自己的序号 seq = x 1。这时 ACK 报文段可以携带数据。但如果不携带数据则不 消耗序号,这种情况下,下一个数据报文段的序号仍是 seq = x 1。这时,TCP 连接已经建立,A 进入 ESTABLISHED(已建立连接)状态。

为什么要三次握手?

TCP 连接使用三次握手的首要原因 —— 为了阻止历史的重复连接初始化造成的混乱问题,防止使用 TCP 协议通信的双方建立了错误的连接。

RST 重置信号

接受方接受到连接请求后,会给发送方发送一个seq 1 的ack, 发送方收到就会判断是否是过期的连接,如果当前连接是历史连接,即 SEQ 过期或者超时,那么发送方就会直接发送 RST 控制消息中止这一次连接。

seq 序列号

TCP 序列号的作用:

接收方可以通过序列号对重复的数据包进行去重; 发送方会在对应数据包未被 ACK 时进行重复发送; 接收方可以根据数据包的序列号对它们进行重新排序;

网络作为一个分布式的系统,其中并不存在一个用于计数的全局时钟,而 TCP 可以通过不同的机制来初始化序列号,作为 TCP 连接的接收方我们无法判断对方传来的初始化序列号是否过期,所以我们需要交由对方来判断,TCP 连接的发起方可以通过保存发出的序列号判断连接是否过期,如果让接收方来保存并判断序列号却是不现实的,这也再一次强化了我们在上一节中提出的观点 —— 避免历史错连接的初始化。

TCP 建立连接时通过三次握手可以有效地避免历史错误连接的建立,减少通信双方不必要的资源消耗,三次握手能够帮助通信双方获取初始化序列号,它们能够保证数据包传输的不重不丢,还能保证它们的传输顺序,不会因为网络传输的问题发生混乱,到这里不使用『两次握手』和『四次握手』的原因已经非常清楚了:

『两次握手』:无法避免历史错误连接的初始化,浪费接收方的资源; 『四次握手』:TCP 协议的设计可以让我们同时传递 ACK 和 SYN 两个控制信息,减少了通信次数,所以不需要使用更多的通信次数传输相同的信息; 我们重新回到在文章开头提的问题,为什么使用类比解释 TCP 使用三次握手是错误的?这主要还是因为,这个类比没有解释清楚核心问题 —— 避免历史上的重复连接。

0 人点赞