CS144_lab4

lab4(未完,待续)


啊,做到lab4,我真的已经快被掏空了,脑子都是一片混乱的,lab的文档有些都看不懂,难度确实太大了(对我来说

最后只能借鉴大佬们的思路了,就摁抄

但还是有些测试用例没通过,不知道是前几个lab的问题还是哪里出错了,哎,累了,过几天有兴趣再搞,pass 掉先

tcp_connection.hh

//! record the time_since_last_segment_received
size_t _time_since_last_segment_received{};
bool _active {true};
//! \brief send the segments from TCPSender's segment_out
void send_sender_segments();
//! \brief brain-bending part, clean shutdown 
void clean_shutdown();
//! \brief brain-bending part, unclean shutdown
void unclean_shutdown();

tcp_connection.cc


size_t TCPConnection::remaining_outbound_capacity() const { 
    return _sender.stream_in().remaining_capacity();
}

size_t TCPConnection::bytes_in_flight() const {
    return _sender.bytes_in_flight(); 
}

size_t TCPConnection::unassembled_bytes() const {
    return _receiver.unassembled_bytes();
}

size_t TCPConnection::time_since_last_segment_received() const {
    return _time_since_last_segment_received;
}

bool TCPConnection::active() const { 
    return _active; 
}

void TCPConnection::segment_received(const TCPSegment &seg) {
    //判断TCPConnection 的状态
    if(!_active){
        return;
    }

    //计时,最近一次 segment 到达的时间
    _time_since_last_segment_received = 0;

    //State: closed
    //发送来的没值,而且下一个要发的byte的absolute seqo是0
    //说明是要建立连接
    if(!_receiver.ackno().has_value() && _sender.next_seqno_absolute() == 0){
        if(!seg.header().syn){
            return;
        }
        _receiver.segment_received(seg);
        connect();
        return;
    }

    //State: syn sent
    //发过syn了且recvived为空,表明未收到发来的syn
    if(_sender.next_seqno_absolute() > 0 && _sender.bytes_in_flight() == _sender.next_seqno_absolute()
    && !_receiver.ackno().has_value()){
        //收到的payload有值,不管
        if(seg.payload().size()){
            return;
        }
        //如果在 syn-sent 状态下,收到对方的 syn
        if(!seg.header().ack){
            if(seg.header().syn){
                // simultaneous open,切换到 State: sent-received 
                _receiver.segment_received(seg);
                _sender.send_empty_segment();
            }
            return;
        }
        //收到 reset
        if(seg.header().rst){
            _receiver.stream_out().set_error();
            _sender.stream_in().set_error();
            _active = false;
            return;
        }
    }

    //收到的是建立连接之后的数据
    _receiver.segment_received(seg);
    //存下ack number,以及weindow size,为下次发送做准备
    _sender.ack_received(seg.header().ackno,seg.header().win);

    // Lab3 behavior: fill_window() will directly return without sending any segment.
    if(_sender.stream_in().buffer_empty() && seg.length_in_sequence_space()){
        _sender.send_empty_segment();
    }

    //建立连接之后收到 reset
    if(seg.header().rst){
        _sender.send_empty_segment();
        unclean_shutdown();
        return;
    }
    //发数据
    send_sender_segments();
}




size_t TCPConnection::write(const string &data) {
    if(!data.size()){
        return 0;
    }
    size_t written_len = _sender.stream_in().write(data);
    
     _sender.fill_window();
    //发送,其实感觉可以没这个发送
    send_sender_segments();
    
    return written_len;
}

//! \param[in] ms_since_last_tick number of milliseconds since the last call to this method
void TCPConnection::tick(const size_t ms_since_last_tick){ 
    //时间检查,超时重发
    if(!_active){
        return;
    }
    _time_since_last_segment_received += ms_since_last_tick;
    //递归等return
    _sender.tick(ms_since_last_tick);
    //超时重传次数过多
    if(_sender.consecutive_retransmissions() > TCPConfig::MAX_RETX_ATTEMPTS){
        //异常
        unclean_shutdown();
    }
    //发
    send_sender_segments();
  
}

void TCPConnection::end_input_stream() {
    // stop outbound byte stream input
    _sender.stream_in().end_input();

    //发送断开连接的segment
    _sender.fill_window();
    send_sender_segments();
}

void TCPConnection::send_sender_segments(){
    
    TCPSegment seg;
    while(!_sender.segments_out().empty()){
        //获取sender头
        seg = _sender.segments_out().front();
        //更新状态
        _sender.segments_out().pop();
        //根据 receiver 的 ackno 值 设置 segments 的标志位
        if(_receiver.ackno().has_value()){
            seg.header().ack = true;
            seg.header().ackno = _receiver.ackno().value();
            seg.header().win = _receiver.window_size();
        }
        _segments_out.push(seg);
    }
    clean_shutdown();
}

void TCPConnection::connect() {
    //给 Sender 上数据
    _sender.fill_window();
    
    //用 TCPConnection 发出去
    send_sender_segments();

}

TCPConnection::~TCPConnection() {
    try {
        if (active()) {
            cerr << "Warning: Unclean shutdown of TCPConnection\n";
            // Your code here: need to send a RST segment to the peer
            // 当调用析构函数,并且 active() 值为 true 时,需要发送一个空的segments附带 RST FALG
            _sender.send_empty_segment();
            unclean_shutdown();
        }
    } catch (const exception &e) {
        std::cerr << "Exception destructing TCP FSM: " << e.what() << std::endl;
    }
}

void TCPConnection::clean_shutdown(){
    if(_receiver.stream_out().input_ended()){
        if(!_sender.stream_in().eof()){
            _linger_after_streams_finish = false;
        }else if(_sender.bytes_in_flight() == 0){
            if(!_linger_after_streams_finish || time_since_last_segment_received() >= 10 * _cfg.rt_timeout){
                _active = false;
            }
        }
    }
}

void TCPConnection::unclean_shutdown(){
    // When this being called, _sender.stream_out() should not be empty.
    _receiver.stream_out().set_error();
    _sender.stream_in().set_error();
    _active = false;
    TCPSegment seg = _sender.segments_out().front();
    _sender.segments_out().pop();
    seg.header().ack = true;
    if(_receiver.ackno().has_value()){
        seg.header().ackno = _receiver.ackno().value();
    }
    seg.header().win = _receiver.window_size();
    seg.header().rst = true;
    _segments_out.push(seg);
}

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值