网络基础-----TCP(深入认识)

一、确认应答(ACK)机制

这里写图片描述
TCP通过肯定的确认应答(ACK实现可靠的数据传输)。当发送端将数据发出去之后,在等待对端的确认应答,如果有确认应答,就说明数据已经成功到达对端,反之,数据丢失的可能性比较大。

二、超时重传机制

在一定的时间内没有等到确认应答,发送端就可以认为数据已经丢失了,并进行了重发。由此,即使产生了丢包,任然能够保证数据到达对端,实现可靠传输。
这里写图片描述
未收到确认应答并不意味着数据一定丢失,也有可能是数据对方已经收到了,只是返回确认应答在途中丢失。这种情况也会导致发送端因没有收到确认应答而重新的发送数据。
这里写图片描述
但是也有其他的一些原因导致应答延迟到达,使源主机重发数据以后才到达的情况也经常见到,对于目标主机来说,就必须引入一种机制,它能够识别是否已经接收数据,又能够判断是否需要接受。
上面的这些确认应答处理,重发控制以及重复控制等功能都可以通过序列号实现。
序列号是按顺序给发送数据的每一个字节(8位字节)都标上号码的编号。接受端查询接受数据TCP首部中的序列号和数据长度,将自己的下一步应该接收的序号作为确认应答返送回去,就这样,通过序列号和确认应答号,TCP可以实现可靠传输。

  • 每一个ACK都带有对应的确认应答号,意思是告诉发送者,我已经收到了哪些数据,下一次你该从哪里进行发送。

    那么超时的时间是如何进行确定的?

  • 找到一个最小的时间,保证确认应答一定能在这个时间内返回

  • 这个时间的长短,随着网络环境的不同,是有差异的。
  • 如果超时时间设的太长,会影响整体的重传效率
  • 超时时间设的太短,有可能会频繁发送重复的数据包。
  • 数据也不会无限、反复地重发,达到重发的次数之后,如果仍然没有任何确认应答返回,就会判定为网络或端主机发生了异常,强制关闭连接。并且通知应用通信异常强行终止。
  • 仍然得不到应答,等4*500ms就进行重传,以指数的形式递增。

三、滑动窗口

确认应答不再是以每个分段,而是以更大的单位进行确认时,转发的时间将会大幅度的缩短,也就是说,发端主机,在发送了一个段以后就不必要的一直等待应答,而是继续发送。
这里写图片描述

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口就是4000个字节。
  • 发送前四个段的时候,不需要等待任何的ACK
  • 操作系统为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前哪些数据没有应答,只有确认应答过的数据,才能从缓冲区中彻底的进行删除。
  • 窗口越大,网络的吞吐量越大
    情况一:数据包已经抵达,ACK被丢了
    这里写图片描述
    这种情况下,部分ACK丢了并不要紧,因为可以通过后序的ACK进行确认。
    情况二、数据包就直接丢了
    这里写图片描述

  • 某一段报文段丢失之后,发送端就会一直1001这样的ACK,就像是在提醒发送端“我想要的是1001”

  • 如果发送端主机连续三次收到了同样一个“1001”,这样的应答,就会将对应的数据1001~2000重新发送。
  • 这个时候接受端收到了1001之后,再次返回的ACK就是7001(因为2001~7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中。
    这种机制被称为“高速重发机制”(也叫做快重传)

四、流量控制

TCP支持根据接收端的处理能力,来决定发送端的处理速度,这个机制就叫做流量控制。(Flow Control )
它的具体操作是,接收端主机向发送端主机通知自己可以接受数据的大小。于是发送端会发送不超过这个限度的数据。该大小限度被称作窗口大小。
这里写图片描述
当停止接收数据之后,发送主机会时不时的发送一个叫做窗口探测的数据段,此数据段仅含一个字节以获取最新的窗口大小信息。

五、拥塞控制

虽然已经有了滑动窗口这个武器,但是在一开始的时候就发送大量的数据,就会引发问题。但是网络上有许多的计算机,可能当前的网络状态就已经非常的拥堵了,在不清楚担当前往络的状态下,发送大量的数据,是有可能引起雪上加上霜的。
TCP引入了慢启动机制,先发少量的数据,摸清楚当前的网络状态,再决定按照多大的速度进行传输数据。
这里写图片描述

  • 在这里我们引入的概念叫做拥塞窗口
  • 发送开始的时候我们定义的拥塞窗口的大小为1
  • 每次收到一个ACK应答,拥塞窗口加1
  • 每次发送数据包的时候,将拥塞窗口的和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口。

    拥塞窗口的增长速度是指数形式的,慢启动指的是初始时慢,但是增长的速度特别快。

  • 为了控制拥塞窗口的速度,不能使窗口单纯的加倍。
  • 我们引入一个叫慢启动的阈值。
  • 当拥塞窗口超过这个阈值的时候,不再按照指数的形式增长,而是按照线性的方式增长。

少量的丢包我们认为是出发超时重传,大量的丢包,我们就认为是网络拥塞
TCP通信开始后,网络吞吐量会逐渐上升,随着网络发生拥堵,吞吐量会立刻下降。

六、延时应答

如果接收数据的主机立刻返回ACK应答,这时候的窗口可能就比较小。
窗口越大,网络的吞吐量就越大,传输效率就越高,我们的目标是保证在网络不拥塞的情况下尽量的提高传输效率。
那么所有的包都可以延迟应答吗?肯定不是的。

  • 数量限制:每隔N个包就应答一次
  • 时间限制:超过最大延迟时间就应答一次

    具体的数量和延时时间,依照操作系统不同也会有差异的。一般N取2,超时时间取200ms

七、捎带应答

在延时应答的基础上,通常,客户端服务器在应用层也是一发一收的,意味着客户端给服务器说了“How are you?”,服务器也会给客户端说句“Fine ,thank you”;
那么这个时候ACK就可以进行搭顺风车了,和服务器回应的“Fine ,thank you”,一起回给客户端。意思是我们在进行数据的收发的时候不需要单独的进行ACK,我们应该将其放在文件中将其一块进行发送。

八、面向字节流

创建一个TCP的socket,同时在内核中创建一个发送缓冲区和接收缓冲区。

  • 调用write的时候,数据会现将其写入到发送缓冲区中。
  • 如果我们 发送的字节数太长的话,会被拆分成多个TCP的数据包发送出去
  • 如果发送的字节数太短,就会想在缓冲区中进行等待,等到缓冲区的长度差不多的时候,或者其他合适的机会进行发送
  • 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区
  • 然后应用程序可以调用read从接收缓冲区中进行拿数据
  • TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这样的一个连接,既可以进行读数据,也可以写数据,这叫做全双工。
    -由于缓冲区的存在,TCP的读和写不需要进行匹配。

九、TCP的粘包问题

粘包中的包指的是应用层的数据包。
如何避免粘包问题?我们的做法就是明确两个包之间的边界。

  • 对于定长的包,每次都按照固定的大小读取即可。
  • 对于变长的包,可以在包头位置,约定一个包总长度的字段,从而也就知道包结束的位置。
  • 对于变长的包,还可以在包与包之间使用明确的分隔符(应用层协议,是程序员自己定的,只要保证分隔符和正文不冲突即可)

    思考:对于UDP来说,是否也存在粘包问题呢?

  • 对于UDP如果还没有上层交付数据,UDP的报文长度仍然存在,同时UDP是一个一个把数据交付给应用层,就有很明确的数据边界。

  • 站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收,不会出现半个的情况。

TCP的异常情况

进程终止会释放文件描述符,仍然可以发送FIN,和正常关闭没有什么区别。
机器重启:和进程终止的情况相同。
机器掉电/网线断开:接收端认为连接已经不存在了,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset,即使没有写入操作,TCP自己也内置了一个保活计时器,会定期的询问对方是否存在,如果对方不在,也会把连接释放。

TCP小结

可靠性
- 校验和
- 序列号(按序到达)
- 确认应答
- 超时重传
- 连接管理
- 流量控制
- 拥塞控制

提高性能

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

    其他

    • 定时器(超时重传定时器,保活计时器,TIME_WAIT定时器等)

猜你喜欢

转载自blog.csdn.net/daboluo521/article/details/80719671