CS 144: Introduction to Computer Networking, Fall 2020
https://cs144.github.io/My Repo
https://github.com/wine99/cs144-20fa
思否主页:https://segmentfault.com/u/wine99
任务
TCP 接受方接收到乱序且可能重叠的报文段,StreamReassembler 需要将收到的报文段按情况送入 ByteStream (lab0 实现的),或丢弃,或暂存(在合适的时候重组送入 ByteStream)。
注意点:
- 报文段包含索引、长度、内容,lab1 的索引从 0 开始增长,不会溢出绕回。
- 任何报文段,包括新收到的和暂存的,只要可以,就应该立刻送入 ByteStream(可能需要手动重组和去重叠)。
- 容量的限制如下图所示。
思路
- 用 set 来暂存报文段,按照报文段的 index 大小对比重载 < 运算符。
- 用 _eof 来保存是否已经收到过有 EOF 标识的段。
- 收到新段时,通过对比新段的 index、length 和 _first_unacceptable,_first_unassembled 对新段进行必要的剪切,然后处理重叠(调用 _handle_overlap)。
- 处理重叠的逻辑:遍历每个暂存段,如果与新段产生重叠,合并暂存段与新段(调用 _merge_seg,总是往新段上合并,合并后删除重叠的暂存段)。
- 合并段的方法:分类讨论,两个段总共会有四种不同的重叠情况,分别处理。
- 处理完重叠后,调用 _stitch_output:遍历所有暂存段,将可合并的暂存段接入 ByteStream 中。
- 最后,当 _eof 为真且 unassembled_bytes 为 0 时,调用 ByteSteram 的 end_input。
代码
stream_reassembler.hh:
class StreamReassembler {
private:
// Your code here -- add private members as necessary.
ByteStream _output; //!< The reassembled in-order byte stream
size_t _capacity; //!< The maximum number of bytes
size_t _first_unread = 0;
size_t _first_unassembled = 0;
size_t _first_unacceptable;
bool _eof = false;
struct seg {
size_t index;
size_t length;
std::string data;
bool operator<(const seg t) const {
return index < t.index; }
};
std::set<seg> _stored_segs = {
};
void _add_new_seg(seg &new_seg, const bool eof);
void _handle_overlap(seg &new_seg);
void _stitch_output();
void _stitch_one_seg(const seg &new_seg);
void _merge_seg(seg &new_seg, const seg &other);
public:
stream_reassembler.cc:
注意 _add_new_seg 中关于 EOF 的处理细节。
#include "stream_reassembler.hh"
// Dummy implementation of a stream reassembler.
// For Lab 1, please replace with a real implementation that passes the
// automated checks run by `make check_lab1`.
// You will need to add private members to the class declaration in `stream_reassembler.hh`
template <typename... Targs>
void DUMMY_CODE(Targs &&... /* unused */) {
}
using namespace std;
StreamReassembler::StreamReassembler(const size_t capacity)
: _output(capacity), _capacity(capacity), _first_unacceptable(capacity) {
}
//! \details This function accepts a substring (aka a segment) of bytes,
//! possibly out-of-order, from the logical stream, and assembles any newly
//! contiguous substrings and writes them into the output stream in order.
void StreamReassembler::push_substring(const string &data, const size_t index, const bool eof) {
_first_unread = _output.bytes_read();
_first_unacceptable = _first_unread + _capacity;
seg new_seg