cs144网络课程2 TCP receiver#

环境#

https://cs144.github.io/assignments/check2.pdf

commit lab1的代码。

merge lab2的代码
git merge origin/check2-startercode

编译/测试
cmake --build build
cmake --build build --target check2

之前的测试还是会跑,这次要实现TCPReceiver

seqno(sn)#

Reassembler中的index用的是uint64_t。pdf中提到如果以100 gigabits/sec传输数据,也要50年才会溢出。基本是绝对安全的。
但是tcp的header空间很宝贵,tcp的seqno和index是一个意思,为32位。就是4gb的空间,需要做wrap around。达到2^32-1时下一个号从0开始。
每个byte占一个seqno。

因为安全等原因,tcp的初始seqno是随机的。

逻辑开始结束都占用一个seqno。

收发两条路的seqno各不相干。

wrap是asn转sn,直接加上isn再取模即可。
unwrap是sn转asn,可能落在多个位置。比如,设sn容量是5,isn是3。

sn    3  4  0  1  2  3  4  0  1  2  3  4  0  1  2  3  4  ...

asn   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 ...

那么sn4可能对应1/6/11/16。
所以它还给定一个checkpoint,比如10,让我们找离10最近的可能值,结果就是11。
最无脑的办法,先用checkpoint除以sn容量,得到一个大致的轮数,再用sn在这个轮数周围(比如+-2)试一个最接近的值出来。这样可通过测试。
可以一步算出来的,我没具体研究。

TCPReceiver#

要把ByteStreamReassembler和tcp协议结合起来,做成一个TCPReceiver

tcp协议
https://www.ietf.org/rfc/rfc9293.html

看一眼第3节tcp的header。seqno和ackno都是32位。

  • 可能需要改进Reassembler,加接口。

  • SYN和FIN都占一个sn,要想办法让Reassembler跳过它们。

  • 收到SYN时确定zero point。之后ackno有效,否则send不要返回ackno。

  • SYN标志着连接的建立。收到SYN后其他数据才有效,之前的抛弃。

  • 可连续收到SYN。rfc3.5节有讨论。

  • SYN、FIN和payload可同时存在于一条消息中。

  • 碰到SYN我直接设置Reassembler的起始sn。

  • 收到SYN和FIN时ackno都要+1。

  • window_size不能大于UINT16_MAX。见rfc的tcp header格式。

  • 如他所说最后代码其实很简洁,receive里用十几行代码就ok了。