结合Packet Tracer理解TCP连接建立

个人认为谢希仁老师的《计算机网络 第七版》对TCP连接建立有些地方表述不够直观和准确,本文分享自己的理解,欢迎讨论。

1. 一个问题

使用TCP协议进行数据传输的过程是这样的:连接建立、数据传输、连接释放。在Cisco Packet Tracer验证下,在Packet Tracer创建一个简单的网络拓扑结构PC -- Server,通过PC向Server发送HTTP请求,抓到如下数据包。

Cisco Packet Tracer抓取TCP报文
图1 Cisco Packet Tracer抓取TCP报文

分析上图抓到的TCP报文,可以画出如下TCP连接建立、数据传输、连接释放示意图,如下:

TCP连接建立、数据传输、连接释放
图2 TCP连接建立、数据传输、连接释放

如果你足够细心的话,会发现从图1抓到的报文时间戳来看,TCP连接建立的最后一个确认报文是在HTTP请求报文之前。为什么?

2. TCP连接建立

谢希仁老师的《计算机网络 第七版》教材给出了TCP连接建立示意图:

TCP连接建立过程
图3 TCP连接建立过程

教材是这么解释上图的:A请求建立连接、B确认请求连接、A再次确认,连接建立过程叫三报文握手。教材有指出步骤2可以拆成两个报文:确认报文、同步报文。这样子的解释,个人认为不够直观。教材随后解释为什么需要最后一次确认,更是让人摸不着头脑。

我认为这样解释会更好。双方进行数据传输之前,需要让对方知道自己的序号(sequence numbers),这样对方才能知道从哪里确认报文。TCP是全双工通信,连接建立需要两个方向都建立。这个过程如下[1]

A ------SYN-----> B    SYNchronize with my Initial Sequence Number of X
A ------ACK-----> B    I received your syn, I ACKnowledge that I am ready for [X+1]

A <------SYN----- B    SYNchronize with my Initial Sequence Number of Y
A <------ACK----- B    I received your syn, I ACKnowledge that I am ready for [Y+1]

将第二步和第三步合并,即服务端向客户端发送确认报文(ACK)和发起连接请求(SYN)放在同一个报文中。也可以理解成报文3捎带(piggyback)了报文2。这样就只有三个报文了,三报文握手(the three way handshake)称呼就是这么来着。

A ------SYN-----> B

A <---ACK/SYN---- B

A ------ACK-----> B

3. 为什么需要最后一次确认

理解了上面的内容,就很容易理解A为什么需要再次发送确认,因为A发送确认是对A <-- B请求连接的确认。

然而,在谢希仁老师的《计算机网络 第七版》第239页,是这样解释A为什么需要再次发送确认:防止已失效的连接请求报文段突然又传到了B。很费解,不过没关系,书中给了一个例子。

A发出的第一个连接请求报文并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。

B收到此失效的连接请求报文段后,就误以为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。但A不会理睬B的确认报文,B的许多资源白白浪费了。

把上面那一段话,画个图,如下:

为什么需要再次发确认
图4 为什么需要再次发确认

关于上述的假设,几点疑问:

  • 请求连接报文延迟那么久,多半在网络节点直接被丢弃了,想想IP报文的TTL字段
  • PC端没收到确认报文,重传。那么服务端收到两个一样的请求报文(确定延迟),会丢弃一个(这点由可靠传输机制保证)

综上,个人认为这样解释为什么需要再次确认站不住脚。事实上,按第二部分理解TCP连接建立过程就很容易理解为什么需要再次发确认,不发不行呀,A <-- B的请求报文需要确认。

另,课本还有一处笔误,P238脚注TCP的标准文档是RFC 793,而不是973,RFC 973是关于Domain System Changes and Observations。

参考资料:

[1] Why do we need a 3-way handshake? Why not just 2-way?

[2] RFC: 793 TRANSMISSION CONTROL PROTOCOL

发表评论

电子邮件地址不会被公开。 必填项已用*标注