-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcp_sender.hh
122 lines (96 loc) · 4.34 KB
/
tcp_sender.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
* @Descripttion:
* @version:
* @Author: xp.Zhang
* @Date: 2023-09-06 10:53:22
* @LastEditors: xp.Zhang
* @LastEditTime: 2023-10-13 10:47:39
*/
#ifndef SPONGE_LIBSPONGE_TCP_SENDER_HH
#define SPONGE_LIBSPONGE_TCP_SENDER_HH
#include "byte_stream.hh"
#include "tcp_config.hh"
#include "tcp_segment.hh"
#include "wrapping_integers.hh"
#include <functional>
#include <queue>
//! \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.
class TCPSender {
private:
//! our initial sequence number, the number for our SYN.
WrappingInt32 _isn;
std::queue<TCPSegment> _segments_outstanding{};
//! outbound queue of segments that the TCPSender wants sent
//只需要把要发送的segment放到这个segment out这个队列里面就行了
std::queue<TCPSegment> _segments_out{};
size_t _bytes_in_flight = 0;
size_t _recv_ackno = 0;
bool _syn_flag = false;
bool _fin_flag = false;
size_t _window_size = 0;
//! retransmission timer for the connection
unsigned int _initial_retransmission_timeout;
//! outgoing stream of bytes that have not yet been sent
ByteStream _stream;
size_t _timer = 0;
bool _timer_running = false;
size_t _RTO = 0;
size_t _consecutive_retransmission = 0;
//! the (absolute) sequence number for the next byte to be sent
uint64_t _next_seqno{0};
public:
//! Initialize a TCPSender
TCPSender(const size_t capacity = TCPConfig::DEFAULT_CAPACITY,
const uint16_t retx_timeout = TCPConfig::TIMEOUT_DFLT,
const std::optional<WrappingInt32> fixed_isn = {});
//! \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
//!@{
//! \brief A new acknowledgment was received
// 接收端返回了确认信息。拿到该确认信息后,首先更新Sender自身的window_size状态。
// 对于接收端确认的ackno来说,如果接收端是对新的数据进行确认,就更新Sender自身的ackno状态。
// (Sender里window_size和ackno存的都是对面Receiver的状态
bool ack_received(const WrappingInt32 ackno, const uint16_t window_size);
//! \brief Generate an empty-payload segment (useful for creating empty ACK segments)
void send_empty_segment();
void send_segment(TCPSegment& seg);
//! \brief create and send segments to fill as much of the window as possible
//接收端会给Sender一个window_size。 根据这个window_size,
//如果窗口没填满,并且发送端有数据需要发送,就可以使用fill_window发送segment
//生成tcp segment 并且发送这些段到segment out 队列中
void fill_window(bool send_syn = true);
//! \brief Notifies the TCPSender of the passage of time
void tick(const size_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_t bytes_in_flight() const;
//! \brief Number of consecutive retransmissions that have occurred in a row
//记录重新传输的数量
unsigned int consecutive_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_t next_seqno_absolute() const { return _next_seqno; }
//! \brief relative seqno for the next byte to be sent
WrappingInt32 next_seqno() const { return wrap(_next_seqno, _isn); }
//!@}
};
#endif // SPONGE_LIBSPONGE_TCP_SENDER_HH