0

这也能考虑到?TCP 有点牛

 1 year ago
source link: https://www.51cto.com/article/746267.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

这也能考虑到?TCP 有点牛

作者:小林coding 2023-02-12 15:47:33
当处于 SYN_SENT 状态连接的客户端,在收到不符合期望的 SYN-ACK 报文时,就直接 RST 给服务端,干掉服务端的旧连接,这样客户端的新连接才能快速建立。

大家好,我是小林。

我在网站看到一位老哥问了个问题。

图片

简单点说,为什么在 TCP 三次握手过程中,如果客户端收到的 SYN-ACK 报文的确认号不符合预期的话,为什么是回 RST,而不是丢弃呢?

图片

我说回 RST 就回 RST 吗?

当然不是,我也是看 RFC 标准确认过。

图片

我来先描述下这个场景吧:

  • 客户端向服务端发送 SYN 报文(seq=100),但是网络中有个不速之客,一个历史的 SYN 报文(seq=90)先抵达服务端;
  • 服务端收到历史的 SYN 报文,就会对此 SYN 报文做了确认,回了 SYN-ACK 报文,确认号为 90+1;
  • 客户端收到 SYN-ACK 报文后,诶发现不对劲,他明明发的是 SYN 报文(seq=100),按道理 SYN-ACK 报文中的确认号是 100+1,可现在收到的确认号为 90+1 的 SYN-ACK 报文,所以礼貌地回了 RST 给服务端;
  • 服务端收到 RST 报文后,服务端就断开处于 SYN_RECEVIED 状态的连接;
  • 最后正常的  SYN 报文(seq=100)终于抵达了服务端,经过三次握手后,双方的 TCP 连接都建立完成。

上面这个过程,就是 TCP 三次握手防止历史连接建立的过程,之所以 TCP 需要三次握手,首要原因是为了防止旧的重复连接初始化造成混乱,其次原因是可靠的同步双方的序列号。

那为什么要设计成,当客户端收到不符合期望的 SYN-ACK 报文,是回 RST,而不是丢弃呢?

现在我们来假设是丢弃处理,看看会发生什么?

图片

可以看到,当处于 SYN_SENT 状态连接的客户端收到不符合期望的 SYN-ACK 报文时,如果选择的处理是「丢弃」,那么双方都会触发超时重传,直到达到最大的重传次数才会进入 CLOSE 状态,这个过程需要持续 10-20 秒。

从客户端的角度看,就是迟迟与服务端建立不来连接,因为服务端这边已经存在一个相同四元组的旧连接,如果不把服务端这个连接干掉,那么是无法确认客户端新的连接(SEQ=100),因为非 LISTEN 状态下,如果收到 SYN,都是回 challenge ack,这个 ack 并不是对收到 SYN 报做确认,而是继续回复上一次已发送 ACK。

是不是有种服务端的旧连接(SEQ=90)占着茅坑不拉屎的感觉?

所以啊,干掉服务端的旧连接的工作,就交给了客户端来做了。

当处于 SYN_SENT 状态连接的客户端,在收到不符合期望的 SYN-ACK 报文时,就直接 RST 给服务端,干掉服务端的旧连接,这样客户端的新连接才能快速建立。

怎么样,TCP 处处是细节啊!

责任编辑:武晓燕 来源: 小林coding

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK