1.流重组器作用
在tcp recevier端对接收到的混乱的字节流进行排序并装入实现的byte_stream中
2.总体思路
1 先将接受到的字节流加入 map中去重并且整理好
2 再将已经排过序的也就是_first_unread 的数据一个个写入out_put中
3.实现的方法
a.使用unordered_map 存储每个char and index的映射关系
b.比较难理解的是map的下标和数据对应关系的判断
c.时刻保证容量的限制不能超过capacity
d.判断eof结束标志位 更新并设置_end_idx=index+sr_written
#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) {}
//! \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) {
//明确传入的三个参数含义
//1.数据 2.数据中第一个字节的在整个字符串的下标 3.是否是最后的字符碎片
//如果data长度过大 就只能截断超出的部分
size_t sr_written_len=data.size();
if(sr_written_len+_map.size()>_capacity){
sr_written_len=_capacity-_map.size();
}
if(index+sr_written_len>_first_unasm+_capacity){
//就是说下标超过接受的最大的限度了
//我们只能接受限度以内的
sr_written_len=_first_unasm+_capacity-index;
}
//以上两个判断是为了维护容量地限制
//如果遇到标识符
if(eof){
_eof=true;
_end_idx=index+sr_written_len;
}
//开始将接受到地字节流 加入 _map中
size_t data_start=0;//从接受到的数据的第data_start位开始读
//如果接收到的index之前已经有序 那就丢弃
if(index<_first_unasm){
data_start=_first_unasm-index;
}
//加入map
for(size_t i=data_start;(i<data_start+sr_written_len)&&(i<data.length());i++){
_map[i+index]=data[i];
}
//尽可能地扩大有序的部分
while(_map.count(_first_unasm)==1){
_first_unasm++;//有序部分加加
}
//尽可能地将有序部分写入byte_stream
string str;
//需要写入的长度
size_t bs_written_len=_first_unasm-_first_unread;
//还需要判断此时byte_stream 又没有足够的空间
if(bs_written_len>_output.remaining_capacity()){
bs_written_len=_output.remaining_capacity();
}
while (bs_written_len>0)
{
str.append(1,_map[_first_unread]);
_map.erase(_first_unread);
_first_unread++;
bs_written_len--;
}
_output.write(str);
if(_eof&&_first_unread==_end_idx){
//结束流
_output.end_input();
}
}
size_t StreamReassembler::unassembled_bytes() const {
//虽然有序但是方不下了
size_t asm_bytes_in_map=(_first_unasm-_first_unread);
return _map.size()-asm_bytes_in_map;
}
bool StreamReassembler::empty() const {
return _map.size()==0&&_output.buffer_empty();
}
#ifndef SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#define SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH
#include "byte_stream.hh"
#include <vector>
#include <cstdint>
#include <string>
#include <map>
#include <unordered_map>
//! \brief A class that assembles a series of excerpts from a byte stream (possibly out of order,
//! possibly overlapping) into an in-order byte stream.
class StreamReassembler {
//流重组器的实现
private:
// Your code here -- add private members as necessary.
size_t _first_unread=0;//第一个还未被读取的
size_t _first_unasm=0;//第一个还未被排序的
bool _eof=false;//结束标志
size_t _end_idx=0;//字节流结束的索引
std::unordered_map<size_t,char> _map{};
//使用这个来对字节碎片进行重组
ByteStream _output; //!< The reassembled in-order byte stream
size_t _capacity; //!< The maximum number of bytes
public:
//! \brief Construct a `StreamReassembler` that will store up to `capacity` bytes.
//! \note This capacity limits both the bytes that have been reassembled,
//! and those that have not yet been reassembled.
StreamReassembler(const size_t capacity);
//! \brief Receives a substring and writes any newly contiguous bytes into the stream.
//!
//! If accepting all the data would overflow the `capacity` of this
//! `StreamReassembler`, then only the part of the data that fits will be
//! accepted. If the substring is only partially accepted, then the `eof`
//! will be disregarded.
//!
//! \param data the string being added
//! \param index the index of the first byte in `data`
//! \param eof whether or not this segment ends with the end of the stream
void push_substring(const std::string &data, const uint64_t index, const bool eof);
//! \name Access the reassembled byte stream
//!@{
const ByteStream &stream_out() const { return _output; }
ByteStream &stream_out() { return _output; }
//!@}
//! The number of bytes in the substrings stored but not yet reassembled
//!
//! \note If the byte at a particular index has been submitted twice, it
//! should only be counted once for the purpose of this function.
size_t unassembled_bytes() const;
//! \brief Is the internal state empty (other than the output stream)?
//! \returns `true` if no substrings are waiting to be assembled
bool empty() const;
};
#endif // SPONGE_LIBSPONGE_STREAM_REASSEMBLER_HH