//! \param[in] capacity the capacity of the outgoing byte stream //! \param[in] retx_timeout the initial amount of time to wait before retransmitting the oldest outstanding segment //! \param[in] fixed_isn the Initial Sequence Number to use, if set (otherwise uses a random ISN) TCPSender::TCPSender(constsize_t capacity, constuint16_t retx_timeout, const std::optional<WrappingInt32> fixed_isn) : _isn(fixed_isn.value_or(WrappingInt32{random_device()()})) , _initial_retransmission_timeout{retx_timeout} , _stream(capacity) {}
//! \param[in] ms_since_last_tick the number of milliseconds since the last call to this method voidTCPSender::tick(constsize_t ms_since_last_tick){ _timecount += ms_since_last_tick;
auto iter = _outgoing_map.begin(); // 如果存在发送中的数据包,并且定时器超时 if (iter != _outgoing_map.end() && _timecount >= _timeout) { // 如果窗口大小不为0还超时,则说明网络拥堵 if (_last_window_size > 0) _timeout *= 2; _timecount = 0; _segments_out.push(iter->second); // 连续重传计时器增加 ++_consecutive_retransmissions_count; } }
//! \brief The "sender" part of a TCP implementation.
//! Accepts a ByteStream, divides it up into segments and sends the //! segments, keeps track of which segments are still in-flight, //! maintains the Retransmission Timer, and retransmits in-flight //! segments if the retransmission timer expires. classTCPSender { private: int _timeout{-1}; int _timecount{0};
//! \name "Input" interface for the writer //!@{ ByteStream &stream_in(){ return _stream; } const ByteStream &stream_in()const{ return _stream; } //!@}
//! \name Methods that can cause the TCPSender to send a segment //!@{ voidsend_tcpsegment(TCPSegment &segment);
//! \brief A new acknowledgment was received voidack_received(const WrappingInt32 ackno, constuint16_t window_size);
//! \brief Generate an empty-payload segment (useful for creating empty ACK segments) voidsend_empty_segment();
//! \brief create and send segments to fill as much of the window as possible voidfill_window();
//! \brief Notifies the TCPSender of the passage of time voidtick(constsize_t ms_since_last_tick); //!@}
//! \name Accessors //!@{
//! \brief How many sequence numbers are occupied by segments sent but not yet acknowledged? //! \note count is in "sequence space," i.e. SYN and FIN each count for one byte //! (see TCPSegment::length_in_sequence_space()) size_tbytes_in_flight()const;
//! \brief Number of consecutive retransmissions that have occurred in a row unsignedintconsecutive_retransmissions()const;
//! \brief TCPSegments that the TCPSender has enqueued for transmission. //! \note These must be dequeued and sent by the TCPConnection, //! which will need to fill in the fields that are set by the TCPReceiver //! (ackno and window size) before sending. std::queue<TCPSegment> &segments_out(){ return _segments_out; } //!@}
//! \name What is the next sequence number? (used for testing) //!@{
//! \brief absolute seqno for the next byte to be sent uint64_tnext_seqno_absolute()const{ return _next_seqno; }
//! \brief relative seqno for the next byte to be sent WrappingInt32 next_seqno()const{ returnwrap(_next_seqno, _isn); } //!@}