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#
要把ByteStream
,Reassembler
和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了。