概述

- 要求用一种模块化的方式实现TCP,上图是本实验的TCP实现的模块图(标注了数据流)
- Lab0实现了ByteStream,在接下来的实验中你将用到它
- “outbound”ByteStream,本地应用程序用它写入字节流数据,TCP将其中的数据发往对等实体
- “inbound”ByteStream,写入从对等实体传过来的字节流数据,本地应用程序将从中读出数据
- Lab1将实现StreamReassembler,用于将一段一段的数据(segments)按顺序拼接成一个完整字节流(这个是TCPReceiver的工作)
- Labs2、3、4将实现TCPReceiver、TCPSender、TCPConnection(将TCPReceiver和TCPSender连接在一起)
- Lab2将实现TCPReceiver,用于处理“inbound”ByteStream(TCP用序列号表示每个字节在字节流中的位置),TCPReceiver将负责告诉发送方
- 已经有多少字节被成功接收并组装(ACK)
- 目前还能再发多少字节的数据(接收窗口大小,用于流量控制)
- Lab3将实现TCPSender,用于处理“outbound”ByteStream
- 发送方怀疑报文段丢失的时候应该怎么处理?
- 什么时候重传报文段?
- Lab4将实现TCPConnection,综合使用前置实验的成果
- 1个TCPConnection包含1个TCPSender和1个TCPReceiver
- 你将用TCPConnection连接到任意的Web服务器
- Lab0实现了ByteStream,在接下来的实验中你将用到它
编写代码前的准备
你应该在Lab0的Sponge代码库的基础上实现本实验
- 确保在此之前已经commit了Lab0的内容(指git的commit?),之后就不要再修改webget.cc、libsponge/byte_stream.hh和libsponge/byte_stream.cc了
- 在项目目录下运行git fetch,确保代码是最新的
- 运行git merge origin/lab1-startercode
- cd build
- make -j4
- writeups/lab1.md是本实验的checkList,需要提交,请认真填写
实现StreamReassembler
概述
- TCPSender会将数据分成一段一段的segment,或者说是substring
- 每一段数据最大为1460字节
- segment在网络中传输时,可能会乱序、丢失、重复
- 所以,TCPReceiver必须将这些segments按原先的顺序重新组装成连续的字节流,本实验将实现StreamReassembler,用于实现这个功能
- StreamReassembler有一个用于输出的ByteStream
- 我觉得下图是一段废话,就不翻译了

- 下图展示了StreamReassembler的接口

- 构造函数,包含capacity参数

- 尝试加入一段数据data,这里的数据应该已经去掉了TCP首部信息
- index指的是当前data的第一个字节的序号(即字节流中的序号)
- eof表示当前data的最后一个字节是否是字节流的最后一个字节

- 返回组装后的字节流

- 返回已经缓存,但未组装到字节流中的字节个数

- 没有已缓存但是没有被组装的数据
- 完整的接口描述在stream_reassembler.hh头文件中,你的任务就是实现这个类
你可以添加任何的私有成员变量和私有方法,但是不能修改公有方法
什么是“capacity”
注意,你的push_substring方法需要忽略所有可能使得StreamReassembler超过其容量的数据部分
- “capacity”:可存储的最大字节数
- 在实现时,你应该将“capacity”视为如下两种数据的上界(注意是两种数据合起来不超过这个上界)
- 已经被重新组装但还未被上层应用读取的字节流中的字节数(下图的绿色部分)
- 已经接收但未被重新组装的字节流中的字节数(下图的红色部分)
FAQs
- 流的第一个字节的序号?0
- 我的实现需要关注效率问题吗?不需要,只要测试在半秒内结束就好了
- 如果出现不一致的substrings该怎么办?可以假设不存在不一致的substrings,即所有的substrings可以组成1个唯一的完整的字节流
- 我可以用什么?你可以用C++基础库中的任何东西,我们希望你能用到至少一个数据结构
- 字节应该在什么时候写入流?As soon as possible
- 只有当它前面的字节没有被push进来的时候,那个这个字节就不能写入
- May substrings provided to the push_substring() function overlap?Yes
- 这句话的意思应该是,调用push_substring传进来的string data这个参数,里面保存的数据可能是重叠的
- 例如,一开始可能传进来[0,1)区间的数据是“a”,然后可能传进来[0,3)区间的数据“abc”,然后可能传进来[1,5)区间的数据“bcde”
- 即两个数据串属于整个流的区间是重叠的
- 我需要给StreamReassembler添加私有成员变量吗?需要,substrings可能乱序到达,所以你需要一个能够缓存substrings的数据结构,直到它们可以被按顺序放入流中

- More FAQs:https://cs144.github.io/lab_faq.html
开发和调试建议
- 你可以在编译代码后运行指令make check_lab1进行测试
- 注意git的使用

- 注意代码的可读性,包括自解释的变量命名、注释;
- defensive programming,显式的检查函数的前置条件或不变量,必要的时候抛出异常

- 使用现代化的C++语法风格
- 你可能会用到move()函数来传递一个不可被copy的对象
- 如果产生一个segmentation fault

- reset the build system

提交注意事项
- 仅修改libsponge顶级目录下的.hh和.cc文件,可以为对象添加私有成员,但不要修改公有接口
- 在提交前,请按顺序运行
- make format
- make
- make check_lab1
- 编辑writeups/lab1.md,文档中需要包含
- 程序设计结构
- 实现过程中遇到的挑战
- 未解决的BUG
- 提交指南:https://cs144.github.io/submit
