CS144 您所在的位置:网站首页 cs144lab2 CS144

CS144

2024-06-17 18:49| 来源: 网络整理| 查看: 265

Lab Checkpoint 2: the TCP receiver

​ Lab2 将实现 TCP 协议的 TCPReceiver,通过 receive() 函数从 peer 端接收数据, 经过 Reassembler 处理写入 ByteStream 缓存, 应用层就可以通过 TCPSocket 读取数据。

​ 在接收 peer 端数据的同时, TCPReceiver 通过 send() 函数承担着告知 peer 一些重要信息的职责, 这些信息包括这两个部分:

Acknowledgment: first_unassembled_index 又称 **ackno**, 是 TCPReceiver 从 peer 发送端希望收到的 第一个字节的索引号。 Flow Control: **window size**, 是 ByteStream 可以写入的剩余空间, 限制了 TCPSender 发送数据的 index 的实际范围。 通过这个 window, TCPReceiver 能够 对输入的数据流量进行控制, 限制发送端的数据直到接收端准备好继续接收。

通常将 ackno 称作 window 的索引左边界 (Smallest Index), 将 ackno + window size 称作 window 的索引右边界 (Largest Index)

2 Checkpoint 2: The TCP Receiver2.1 Translating between 64-bit indexes and 32-bit seqnos

​ Reassembler 重组 substrings 时每一个字节的索引号都是 64-bit, 并且其首位 index 始终是从零开始。 这是一组在当前技术条件下永远不可能溢出的数据流索引号组。 但是在 TCP segment 的头部数据中,sequence number (seqno) 是 32-bit 的, 这组索引号与前述的数据流索引号在长度上不匹配,这种不匹配引入了一些复杂性:

TCP 的数据流可以任意长,但 TCP 报文段的头部 seqno 仅有 32-bit,4 GB大小,当 seqno 达到 $2^{32}-1$ 后,会被置零; 为提高鲁棒性和避免数据混淆,TCP seqno 以一个 32-bit 的随机值作为起始,被称作:**ISN (Initial Sequence Number)**,代表了当前数据流的 “zero point”,或称其为 SYN (beginning of stream); 有 SYN (beginning of stream) 自然也有 FIN (end of stream), 它们不属于数据流中的任意字节,仅作为数据流的起始和末尾的两个标识符存在,但 SYN 和 FIN 分别占一个 seqno;

Transmitting at 100 gigabits/sec, it would take almost 50 years to reach $2^{64}$ bytes. By contrast, it takes only a third of a second to reach $2^{32}$ bytes.

​ CS144 区分了三种类型的索引值:seqno,absolute seqno, 以及 stream index,并给出了一个 “cat” 数据的例子。这些索引需要我们实现其相互之间的转换,并保持转换前后不同数据的这三类索引值之间的关系一致。

wrap:将 absolute seqno $\rightarrow$ seqno

1static Wrap32 Wrap32::wrap( uint64_t n, Wrap32 zero_point )

这个的实现很简单,只需要 zero_point + n 再转换成 Wrap32 即可。

12345Wrap32 Wrap32::wrap( uint64_t n, Wrap32 zero_point ){ // n implicitly convert to uint32_t in order to match the signature of operator+ return zero_point + n;}

unwrap:将 seqno $\rightarrow$ absolute seqno,这个要麻烦一些。

1uint64_t unwrap( Wrap32 zero_point, uint64_t checkpoint ) const

关于 checkpoint 的作用:E.g. 如果 ISN 为 $0$,seqno $17$ 可能对应着多个 absolute seqno: $17$、$2^{32}+17$、$2^{33}+17$、$2^{33}+2^{32}+17$、$2^{34}+17$、$2^{34}+2^{32}+17$ 等等。文档指出:”The wrap/unwrap operations should preserve offsets—two seqnos that differ by 17 will correspond to two absolute seqnos that also differ by 17.” checkpoint 能帮助避免歧义,这里实际上就是 first_unassembled_index。

因此可以将 checkpoint(64位)利用上面的 wrap 函数转换为 ckpt(32位),计算 raw_value 和 ckpt 之间的偏移量 offset,再加到 checkpoint 上。这样最终的结果可以大概写成这样:return checkpoint + (raw_value - ckpt) 。

而对于任意一个 $32$ 位的 seqno,有两个点最靠近 checkpoint,一个在左边,一个在右边。在 $32$ 位空间中,从一个点到另一个点,既可以向右移动 $X$ 距离,也可以向左移动 $2^{32}-X$,对应到 $64$ 位空间中,就是 checkpoint 右边:checkpoint + X,左边:checkpoint - (2^32 - X),因此只需要判断 $X$ 和 $2^{32}-X$ 哪个更小即可。还有一种特殊情况,即如果 checkpoint 不够左移(checkpoint < 2^32 - X),那么就只能选右边的点。

12345678910111213uint64_t Wrap32::unwrap( Wrap32 zero_point, uint64_t checkpoint ) const{ static constexpr uint64_t TWO31 = 1UL


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有