什么是 TCP ?
TCP ( Transmission Control Protocol ) 是一种可靠的,基于字节流的通信传输协议。 相比与 UDP ( User Datagram Protocol ),它提供了更可靠的传输、流量拥塞控制与数据顺序控制。
本篇文章将会简单介绍TCP的一些规则和特性,对于一些复杂且深入的算法,日后有机会单独拎出来和大家分享。
TCP 的实现机制
接下来我们将深入了解一下复杂且功能强大的 TCP 是如何实现的。
报文格式
源/目的端口号:采用端口号来实现同一时刻对多个应用同时发送和接受数据。 序号:用来标识报文段的唯一性。第一个TCP报文段中,序号值被系统初始化为某个随机值。那么在该传输方向上,后续的TCP报文段中序号值将被系统设置成之前的随机值加上该报文段所携带数据的第一个字节在整个字节流中的偏移。
响应值:用作对放发来报文的响应,值为收到的报文段序号加1。 头部长度:标志该TCP头部有多少长。因为4位最大能标识15,所以TCP头部最长是60字节。
保留位:保留以后使用。 TCP标志位:用来存储 TCP 报文现在状态。 URG – 紧急指针,接收端接收到该状态不论是否有缓冲区数据待处理,都会优先处理该报文。 ACK – 确认标志,表示确认号是否有效。 PSH – 提示接收端应该立即从TCP接收缓冲区取走数据,为后续的数据让出空间。 RST – 表示要求对方重新建立连接。 SYN – 请求建立一个连接。 FIN – 对方要关闭连接了。 窗口:用于流量控制,下文我们会讲解。 效验和:通过 CRC 算法来检验 TCP 报文( 包含数据 ) 是否存在损坏或丢失。 紧急指针:它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。当URG位为1时,TCP头部节点的紧急指针位会记录一个偏移量,指向紧急数据的最后一位,在读取到紧急指针所指向的位置之前,TCP的接受进程都处于紧急状态,当读取到紧急数据后一位时,回复到正常状态。
选项:一些扩展字段三次握手
为了准确无误地将数据送达目标处,TCP 协议采用了三次握手策略。用 TCP 协议把数据包送出去后,TCP 不会对传送后的情况置之不理,它一定会向对方确认是否成功送达。
三次握手主要流程如下:
发送端发送一个带 SYN 标志的数据报给对方。 接收到收到以后要返回SYN/ACK 来表示其正确收取到信息。 发送端再回传一个带有ACK标志的数据包来代表握手结束。如果握手过程中出现了异常,将会按照顺序进行重试。
名词解释:
SYN 报文:用于建立连接 ACK 报文:表示响应 SYN/ACK:表示建立连接的响应经过三次握手后,发送端和接收端都已经确定了对方的状态,接下来就可以开开心心的互相传输数据了。
四次挥手
建立一个连接需要三次握手,那么终止一个连接需要什么呢?答案就是四次挥手。
发送端发送一个 FIN 报文,并停止发送数据,且主动关闭TCP连接。进入 FIN_WAIT1 状态,等待接收端的确认。 接收端收到 FIN 报文后,会回复 ACK 报文,并把序列号+1 。切换状态为 CLOSE_WAIT。此时的 TCP 处于半关闭状态,发送端到接收端的连接释放,发送端接收到接收端的确认请求后进入 FIN_WAIT2 的状态。
接收端如果也想断开连接,就重复(步骤1)的操作。发送 FIN 报文给发送端,此时接收端处于 LAST_ACK 状态,等待发送端的最后确认。发送端收到 FIN 之后也会发送一个 ACK 作为应答,并把序列号 +1。
此时发送端处于 TIME_WAIT 状态,需要等待计时器后释放连接。而接收端在收到响应时便进入了 CLOSED 状态,
名词解释:
FIN 报文:表示关闭连接。 FIN/ACK 报文:表示关闭连接的响应。 FIN_WAIT1 状态:等待远程TCP连接中断请求,或先前的连接中断请求的确认。 FIN_WAIT2 状态:从远程TCP等待连接中断请求。 CLOSE-WAIT 状态:等待从本地用户发来的连接中断请求。 LAST-ACK 状态:等待原来的发向远程TCP的连接中断请求的确认。 TIME-WAIT 状态:等待足够的时间以确保远程TCP接收到连接中断请求的确认。 CLOSED 状态:没有任何连接状态。超时与重传
前面我们讲过了如何建立连接,如何释放连接。那么,TCP 在传输过程中如何对丢包进行重传的呢?
要解决丢包的问题,首先要面临的就是怎么来判断丢包了 ?
从第一直觉来看,基于 TCP 的规则。当发送端发送一个数据包后等待接收接收端的 ACK 报文。 如果在一定的时间内未收到该 ACK 报文,那么就有可能会丢包了。
看似不错的计划。但是,这里面有一个重要的问题就是,我们超时的时间该如何定义。
重传超时 ( RTO )TCP 在发送数据时会设置一个计时器,若至计时器超时仍未收到数据确认信息,则会引发相应的超时或基于计时器的重传操作,计时器超时称为重传超时( RTO )。
简单一点,我们可以把该计时器重置成固定的秒数,例如300ms。当发送端发送数据后超过300ms 未收到相应的 ACK 响应则会被认为以超时并进行重传。
该方案在稳定的网络环境内不会出现任何问题,因为大家的网速都很快。但是当出现长延时的请求时就会发生 “雪崩” 了。例如,你要发送一个请求从中国到美国,由于网络延时,每一个请求都会超过所设定的计时器。 这样就导致所有的请求都在无休止的重试。从而引发 “雪崩”。
由此可见,我们需要基于 RTT ( Round-Trip Time )来进行动态的修改RTO。
如何实现动态修改TCP 在收到数据后会返回确认信息,因此可在该信息中携带一个字节的数据( 特殊符号 )来测量传输该信息所需要的时间。每个此类的测量结果称为 RTT 的样本。TCP 需要根据一段时间的样本建立好估计值。接下来在基于该值去计算RTO。
计算 RTO 也是一个非常复杂的讨论,鉴于我们只是想简单了解 TCP 协议,则不深入展开。
名词解释:
RTT : 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。 快速重传机制快速重传机制基于接收端的响应信息来进行判断是否需要重发。相比于传统的计时器模式,快速重传机制能更加及时的修复丢包情况。
当失序数据到达时,接收端会返回重复 ACK 报文来定位其具体位置,由于我们无法得知重复的 ACK 报文是具体由于丢包还是由于网络延时导致。因此TCP 等待一定树木的重复ACK( ACK 阈值 )来决定数据是否丢失并触发快速重传。
名词解释:
ACK 阈值:该值通常为 3,在一些非标准化的实现中可基于当前的失序程度动态调节。 重复ACK 报文:基于TCP 规则,在进行返回ACK 报文时会将该报文加 1 的序列号返回 ( 也就是说每个ACK 返回的值将是它所需要的下一个数据包的序列号 )。当接收端一直无法接收到需要的数据包时,将会向发送端发送具有重复序列号的ACK 确认报文。以此来判断哪一个数据报丢失了。免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:物联网传输协议基石 – TCP ( Transmission Control Protocol )上 https://www.yhzz.com.cn/a/12708.html