赞
踩
“ 无论在互联网领域还是汽车以太网领域,TCP/IP 协议族中传输层的传输控制协议(Transmission Control Protocol,TCP)都有举足轻重的作用和大量的应用场景。TCP 是一种面向连接的、可靠的、基于字节流的通信协议,最初由 IETF RFC 793 定义,后续在 RFC 1122、RFC 2581 等文档中都进行了修订和补充。
不同于另一个同样位于传输层的用户数据报协议(User Datagram Protocol,UDP),TCP 的工作原理和交互机制要复杂很多,比如我们熟知的三次握手、四次挥手、发送确认以及状态机跳转等。本文把这些复杂的工作机制以图示的形式展示出来(个人认为图片的美观程度是全网最好的,些许强迫症,花了不少时间画的),希望能够帮助大家更好的理解 TCP 协议。”
开篇先送大家一个好看的 TCP 报头(遵循 RFC 793):
注:文中提到的 SYN 报文、FIN 报文或 ACK 报文指的是对应标志位置 1 的 TCP 数据段。
TCP 状态机示意图
TCP 三次握手建立连接示意图
上图为 TCP 三次握手的示意图,三次握手其实是通过三条 TCP 报文来建立连接的过程。主动打开连接的一端为 Client(图中的 ECU A),被动打开连接的一端为 Server(图中的 ECU B),这里的 Active OPEN 表示主动打开并发送 SYN 报文,相当于调用了 connect () 函数;Passive OPEN 表示被动打开并进入监听状态,相当于调用了 listen () 函数。
TCP 同时打开并建立连接示意图
TCP 同时打开是一个特殊的情况,两端均想主动发起并建立连接,会同时发送 SYN 报文,在自己的 SYN 报文被对端确认之前,会先收到了对端请求建立连接而发送 SYN 报文,这时两端只需回复 SYN+ACK 报文,即可建立连接。
TCP 数据传输示意图
TCP 之所以可靠,除了建立连接、释放连接之外,还有数据确认、数据重传等工作机制,TCP 会给所要传输数据的每一个字节进行编号,也就是数据的序列号。数据传输完成后,对端会回复 ACK 报文进行确认,当一直未收到确认报文时,TCP 会启动重传机制,以保障了数据传输的可靠性。上图为数据传输和确认的示意图,图中的 SEQ 和 ACK 分别表示 TCP 报头中的序列号(Sequence Number)和确认号 (Acknowledgement number)。ECU A 和 ECU B 已经经过三次握手进入了 ESTABLISHED 状态,开始进行数据的收发,为了更好的介绍,我们假设 ECU A 当前传输数据的 SEQ = 1,ECU B 当前传输数据的 SEQ = 11,实际上,真实的 TCP 在建立连接时,为了防止网络攻击等情况,初始序列号 (Initial Sequence Numbers,ISN) 会是一个随机选择的很奇怪的数字。
自己发送的 TCP 报文的 SEQ 是和上一条接收到的对端发来的 TCP 报文的 ACK 相关联的,图中同样颜色的即为相关联的数字。ECU A 发送数据的第一个字节 SEQ = 1,所传输数据长度为 100 字节,也就是说 ECU A 现在要传输序列号 1 到 序列号 100 这 100 个字节的数据。如果数据被正确接收,ECU B 会回复 ACK 报文,报文中的 ACK = 101,表示 101 序列号之前的所有数据都已被我正确接收。这就是简单的发送和确认机制,图中我还举了一个例子,大家可以自己计算下。
TCP 四次挥手释放连接示意图
TCP 四次挥手是当数据传输完成后,两端想释放连接时,通过四条报文的交互进行连接关闭的过程。想主动关闭连接的一端(ECU A)会调用 close()函数(或者 shutdown()函数,因为不是专业码农,具体的区别就不多介绍了,免得说错),进而发出 FIN 报文,接收端(ECU B)收到对端的 FIN 报文后,会回复 ACK 报文进行确认。这时 ECU B 会询问自己的上层应用,是否还是数据要发送、是否需要关闭连接。如果还有数据发送,这时数据还是可以从 ECU B 发送至 ECU A 的(途中绿色 “ 数据传输 ” 箭头)。当所有数据均传输完成后,ECU B 也会调用 close()函数,发送 FIN 报文。四条报文传输完,被动关闭的一端会直接跳转至 CLOSE 状态,但主动关闭的一端会进入 TIME-WAIT 状态,在等待两个 MSL (Maximum Segment Lifetime,此值可配置,通常默认为 60 秒) 超时之后才会跳转至 CLOSE 状态,至此,四次挥手结束,连接关闭。等待 2 * MSL 是为了防止最后一条 ACK 未被 ECU B 正确接收,等待 ECU B 进行 FIN 报文重传的时间 。
TCP 同时关闭并释放连接示意图
TCP 同时关闭和同时打开类似,两端同时关闭连接,同时调用 close()函数时会出现这种情况。这里会多一个四次挥手时不会出现的状态:CLOSING,当自己发出的 FIN+ACK 报文在未被对端确认就收到了对端请求关闭连接的 FIN+ACK 报文时,会直接回复 ACK 并跳转至 CLOSING 状态,直到收到了对端确认自己 FIN 报文的 ACK后 ,才会进入TIME-WAIT 状态,进而等待超时关闭连接。
图片:
在以太网通信中,TCP 是一个非常基础的协议,如果大家对车载以太网有兴趣,可以关注公众号“汽车以太网”,和王师傅交流讨论。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。