将子串按顺序排列
在本实验和下一个实验中,您将实现一个 TCP 接收器:接收数据报并将它们转换为可靠的字节流以供用户读取(就像您的webget 程序从实验 0 中的 webserver 读取字节流)。
TCP 发送方将其字节流分成短段(子串不超过每个大约 1,460 字节),以便它们每个都适合数据报。但是网络可能重新排序这些数据报,或者丢弃它们,或者多次传送它们。接收者必须将这些段重新组合成它们开始时的连续字节流。
在本实验中,您将编写负责此重组的数据结构:流重组器。它将接收子串(由一串字节和索引组成较大流中字符串的第一个字节)并提供一个 ByteStream 与所有数据正确排序。
界面如下所示:
// 构造一个 `StreamReassembler`,最多可以存储 `capacity` 个字节。
StreamReassembler( const size_t capcity);
// 接收一个子字符串并将任何新的连续字节写入流中。
//
// `data`: 段
// `index` 表示 `data` 中第一个字节的索引(按顺序放置)
// `eof`:该段的最后一个字节是整个流中的最后一个字节
void push_substring ( const string & data, const uint64_t index, const bool eof);
// 访问重组的字节流
const ByteStream stream_out();
// 已存储但尚未重组的子串中的字节数
size_t unassembled_bytes () const ;
// 内部状态是否为空(输出流除外)
bool empty() const ;
重组器的完整(公共)接口由 StreamReassembler 类描述在流 reassembler.hh 标头中。你的任务是实现这个类。您可以添加您希望 StreamReassembler 类的任何私有成员和成员函数,但是你不能改变它的公共接口。
?我为什么要这样做?
因为它是 TCP 对段的健壮性的核心重新排序,它将使处理传入的段变得更加容易。
常见问题
? 整个流中第一个字节的索引是多少?零。
? 我的实施应该有多高效?我们不会指定一个特定的还没有效率的概念,但请不要将其视为构建粗犷空间的挑战-或时间效率低下的数据结构——这种数据结构将成为你的基础TCP 实现。
? 如何处理不一致的子串?你可能认为他们没有存在。也就是说,您可以假设存在唯一的底层字节流,并且所有子字符串是它的(准确)切片。
? 我可以使用什么?您可以使用标准库的任何您觉得有用的部分。在特别是,我们希望您至少使用一种数据结构。
? 什么时候应该将字节写入流?尽快。唯一的情况在哪个字节不应该在流中是当它之前有一个字节时还没有被“推”过。
? 子串可以重叠吗?是的。
? 我是否需要向StreamReassembler 添加私有成员?是的。由于字串可能以任何顺序到达,您的数据结构将必须“记住”子字符串,直到它们准备好放入流中——也就是说,直到它们之前的所有索引都被填满。
实验结果


实验总结
这个实验主要是利用lab0写的读写字节流,完成一个字节重组器,对不按序到达的字串重组,排序好后读入字节流中,测试程序会自动读取字节流中的数据.

根据实验指示图,我们需要写一个数据结构,维持容量为capcity,绿色部分代表已经读入字节流但是还没读出的部分,红色部分代表存入数据结构,
但是还没有重组的部分,蓝色部分表示已经从字节流中读出的部分。
我们接受到data后,将不能重组的部分存储起来,如果能重组则直接重组,然后直接读入字节流。
不用担心读入失败问题,因为初始化时设置字节流的最大容量capcity和我们的数据结构维持的width是一样的,即绿色的部分永远小于width,所以只要能放进width的部分就可以直接读入字节流.
接受到data时,可能有超界的情况,比如:
