从问题出发考虑TCP的设计原理

  1. 信息通信里,不可避免信息量会有损,如何解决这个问题,保证信息传输是完整而正确的?
  • 第一种方式是差错校验码,通过添加冗余的比特,以恢复真实信息。
  • 第二种方式是尝试重新发送,直到接收方收到正确的信息。
  1. 假如简单地使用尝试重新发送方法,需要哪些方式判断接收方已正确接收信息?
  • 接收方是否收到分组?
  • 接收方收到的分组是否与发送方发送的一样。
  • 对于两个问题问题, 可以向发送方发送确认[ACK],但同样伴随着一些新的问题。
  • 如果 ACK 丢失了怎么办?
    • 重发就好了,但可能会导致接收方收到冗余数据,因此接收需要对这种情形做处理,这个问题可以用序列号解决,重复的序列号丢弃。
  • 如果分组收到了,但里边有错怎么办?
    • 用额外的数据对错误的编码进行纠正。
    • 用校验和检测数据正确性,如果错误则不发送 ACK,等待重发。
  • 发送方对一个 ACK 应该等待多长时间?
    • 即超时重传的时间,这取决于发送耗时+接收方处理耗时+ACK返程耗时,这很难估计,因为收到硬件设备的影响,所以只能通过预估。预估策略可以是统计然后算出均值,动态设置超时时间,但并非如此简单,因为有些样本是异常的,不能参与统计计算。总得来说时间预估是可行的,只是比较复杂,这里暂且不表,只提个大概。
  1. 目前为止,可以保证接收方收到正确的信息,但这是建立在分组是同步地、有序地去发送的前提下。这样效率不高,因为需要等待 ACK 顺利送达之后才能进行下一步,中间如果出现丢包或者时延过高,传输效率会大幅降低,如何解决这个问题?
  • 同步不行考虑并行,可以同时发送多个分组,但并行会增加通信的复杂度,带来以下问题:
    • 3-1 什么时候发?
    • 3-2 发多少?
    • 3-3 每个分组在等待ack时,如何维持计时器?
    • 3-4 需要维持每个分组的备份以备重传
    • 3-5 接收方需要区分哪些分组已收到,哪些没有
    • 3-6 接收方还需要维护分组的次序
    • 3-7 如果接收方的接收速率比发送方慢怎么办?
  1. 如何解决并行分组带来的问题?
  • 为了解决问题 3-4、3-5、3-6
    • 首先,定义一个数组,数组的元素是每个分组,再定义一个长度N指代允许并行发送的分组大小。接下来分步骤:
      1. 初始状态下,下标0~N是允许并行发送的分组。(解决3-4)
      2. 0~N的分组并行发送,然后出于等待ACK的状态下。
      3. 假如0号分组收到ACK,则下标1~N+1为允许并行发送的分组,0号分组因为收到确认,可以从数组中移除了。
      4. 任何新来的分组,都应塞在数组最后。
    • 接收方同理,数组上分配着已接收、已确认、期待接收的分组。(解决3-5、3-6)
    • 此方法称为滑动窗口,由N个格子在数组上滑动可以看出来。然而N应该多大?(4-1)
  • 为了解决问题 3-2、3-7
    • 既然发送方太快,那我们就让他慢一点嘛,让他的发送速度永远不超过某个速度即可。
    • 另一种方法是动态控制窗口N的大小,由接收方在ACK携带窗口大小的通告,这样能保护接收方。至于中间节点如路由器,则要依赖拥塞控制算法,这里暂且不表。