CS144计算机网络_Lab2_索引转换

112 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

TCP 报文中用来描述当前数据首字节的索引(序列号 seqno)是32位类型的,这意味着在处理上增加了一些需要考虑的东西:

  • 由于 32位类型最大能表达的值是 4GB,存在上溢的可能。因此当 32位的 seqno 上溢后,下一个字节的 seqno 就重新从 0 开始。

  • 处于安全性考虑,以及避免与之前的 TCP 报文混淆,TCP 需要让每个 seqno 都不可被猜测到,并且降低重复的可能性。因此 TCP seqno 不会从 0 开始,而是从一个 32 位随机数起步(称为初始序列号 ISN)。

    而 ISN 是表示 SYN 包(用以表示TCP 流的开始)的序列号。

  • TCP 流的逻辑开始数据包逻辑结束数据包各占用一个 seqno。除了确保接收到所有字节的数据以外,TCP 还需要确保接收到流的开头和结尾。 因此,在 TCP 中,SYN(流开始)和 FIN(流结束)控制标志将会被分别分配一个序列号(SYN标志占用的序列号就是ISN)。

    流中的每个数据字节也占用一个序列号。

    但需要注意的是,SYN 和 FIN 不是流本身的一部分,也不是传输的字节数据。它们只是代表字节流本身的开始和结束。

字节索引类型一多就容易乱。当前总共有三种索引:

  • 序列号 seqno。从 ISN 起步,包含 SYN 和 FIN,32 位循环计数
  • 绝对序列号 absolute seqno。从 0 起步,包含 SYN 和 FIN,64 位非循环计数
  • 流索引 stream index。从 0 起步排除 SYN 和 FIN64 位非循环计数。

序列号和绝对序列号之间相互转换稍微有点麻烦,因为序列号是循环计数的。在该实验中,CS144 使用自定义类型 WrappingInt32 表示序列号,并编写了它与绝对序列号之间的转换。

WrappingInt32

class WrappingInt32 {
  private:
    uint32_t _raw_value;  //!< The raw 32-bit stored integer
​
  public:
    //! Construct from a raw 32-bit unsigned integer
    explicit WrappingInt32(uint32_t raw_value) : _raw_value(raw_value) {}
​
    uint32_t raw_value() const { return _raw_value; }  //!< Access raw stored value
};
​
WrappingInt32 wrap(uint64_t n, WrappingInt32 isn);//将64位转为WrappingInt32
uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint);//将WrappingInt32转为64位