Standford CS144 lab2
Lab2 the TCP receiver
- 
总览
- 这次实验要实现TCP receiver,它将
TCP segments转换为字节流 - TCP receiver 通过segment received() 方法接收segments
 - TCP receiver还需要告知
发送方确认号ackno,也就是第一个unassembled 的字节号,ackno又称为left edge, 而ackno + windowsize又称为right edge - TCP receiver 还需要告诉
发送方接收窗口大小window size,也就是first unassembled和first unacceptable之间的大小 接收窗口window size可以使发送方实现流量控制- 这个lab最难的部分
The hardest part will involve thinking about how TCP will represent each byte’s place in the stream—known as a “sequence number. 
 - 这次实验要实现TCP receiver,它将
 - 
实现64-bit的字节流下标与32-bit的序列号之间的转换
- 在lab1中实现的字节流重组器的字节有64bit的流下标,64bit的下标可以看成无限大
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.但是TCP头部的序列号只有32个字节大小,所以需要转换 - 序列号2^32 - 1下一个就是0
 - 为了提高安全性与避免过期的报文与当前报文产生冲突,TCP 序列号开始于一个随机的值,它被叫做
Initial Sequence Number (ISN),该序列号用于SYN,也就是建立连接 SYN需要占一个序列号,而FIN也需要占一个序列号,SYN表示字节流的开始,FIN表示字节流的结束- 接收方与发送方两端都有一个字节流,都有一个
random ISN - 之后会提及
absolute sequence number,也就是不会绕回的序列号,与stream index的概念,也就是字节流的下标,对于一个
 - 在这个lab中,序列号是一个定制化的类型
WrapppingInt32,也就是uint32_t加上一些函数与操作符,而绝对序列号用uint64_t表示 - 需要实现一个wrap函数,用于
绝对序列号到序列号的转换 - 需要实现一个unwrap函数,用于用于
序列号到绝对序列号的转换,一个序列号可能对应多个绝对序列号,比如ISN是0,而序列号为17,可以对应绝对序列号2^32 + 17, 2 ^ 33 + 17等,可以通过把the last reassembled byte作为衡量点(checkpoint)来解决该问题,并且lab提供了帮助函数,在TCP实现中,the last reassembled byte充当checkpoint 
 - 在lab1中实现的字节流重组器的字节有64bit的流下标,64bit的下标可以看成无限大
 - 
实现TCP receiver
- 
lab中会用到TCPSegment类,它的length in sequence space()方法会很有用,用来计算在该TCPSegment中有多少序列号,SYN与FIN也会占据一个序列号;以及TCPHeader类
 - 
需要实现三个方法,
segment received(),ackno(),window size() - 
std::optional用到了CPP17新特性optional, 可以参考,大概就是说可以更优雅的处理空值的情况,通过返回nullopt,另外为了解决编译器报错,做以下修改ackno() const; 
 - 
实现
- TCPreceiver将接收到的TCPsegment做处理,讲有效的字节序列放入
StreamReassembler中,当然需要对TCPsegmen做相应处理, - 实际上,
StreamReassembler中的ByteStream就是TCPreceiver的缓存,StreamReassembler起到一个中间处理的作用,ByteStream是实际缓存,那么三者的capacity是一致的 
 - TCPreceiver将接收到的TCPsegment做处理,讲有效的字节序列放入
 - 
实现中遇到的问题
- 本来没看懂lab要我做什么,就想着去看别人的,看了好几个都好长,好难懂,就自己写了;SYN占一个序列号,虽然文档中强调了,由于_isn设置为了syn的序列号,那么获取当前序列号对应的absolute sequno,
hdr.seqno + (hdr.syn ? 1 : 0)表示syn占据了一个序列号 - 对于_fin的置位,需要fin置位的TCPsegment收到了,且没有因为窗口大小问题被丢弃;并且只有当_fin置位,字节流的中所有的字节都被push了,那么才需要考虑fin占据了一个序列号
 
 - 本来没看懂lab要我做什么,就想着去看别人的,看了好几个都好长,好难懂,就自己写了;SYN占一个序列号,虽然文档中强调了,由于_isn设置为了syn的序列号,那么获取当前序列号对应的absolute sequno,
 
 - 
 
ASAP是as soon as possible