cs144网络课程3 TCP sender#
环境#
https://cs144.github.io/assignments/check3.pdf
commit lab2的代码。
merge lab3的代码
git merge origin/check3-startercode
编译/测试
cmake --build build
cmake --build build --target check3
TCPSender#
TCPSender
需要干一系列事情
关注
TCPReceiver
的window。从本地
ByteStream
取数据,根据对端的window组成tcp包给对端。关注发出去的包是否被对端ack。
超时没被ack的包,重发。
可以看看rfc9293中的rto相关内容。
多久算超时?按https://www.ietf.org/rfc/rfc6298.html第5节推荐的算法来。
实现#
Push
用byte_stream_helpers.cc
中的read()
从Reader
中取数据。
生成TCPSenderMessage
待发送。payload不要大于TCPConfig::MAX PAYLOAD SIZE
。可生成多个。ExpectMessage
会用maybe_send
拿到一个TCPSenderMessage
,然后检查它是否符合要求。
maybe_send
就是上层应用来取tcp包的接口,取走就是已发送。ExpectNoSegment
调maybe_send
。期望无消息,如果发了消息,报错。ExpectSeqno
调send_empty_message
。返回空的TCPSenderMessage
,只填seqno。
用于检测seqno是否正确。ExpectSeqnosInFlight
用sequence_numbers_in_flight
检查发出且未ack的字节数。
push时一旦从Reader中取出数据就要计数。跟踪ack
接收方只有收到了连续的数据才会ack。可能存在连发几个ack,比如[1 5 12],但是sender收到的顺序为[5 12 1]。
这样没问题,因为一旦ack就意味着之前的数据都已经成功收到。
只需维护一个数,看到更大的ack直接更新就行,老的直接抛弃。这里的1直接抛弃。
如果收到的ack大于目前已发送的,为非法,抛弃。
ack底层应该维护安全的64位数据?
ack可能处于数据包的中段,这种情况可以不处理,只处理ack覆盖一个完整包的情况。AckReceived
调receive
收数据。完了默认会push一下。
每次收到数据时要更新window_size
,后续的发送总长度不能超出。直到再次更新。
如果接收端返回window_size
为0,要强行使window为1,发送一个数据以便能收到新的window_size
。否则可能永远卡住。
window_size
为0情况下rto不要加倍。Tick
调tick
更新时钟。
每次更新时钟时检查超时重发流程。initial_RTO_ms
为初始超时时间。
只要存在已发出未ack的数据,就要保证timer开启。
只有一个timer,并不是每个数据包一个timer。
重发的永远是未ack数据包中sn最小的那个。
每超时一次rto加倍。要记录连续重发次数,consecutive_retransmissions
中返回给上层。
一旦出现有效的ack,关timer,rto恢复初始值。如果仍存在其他等待ack的包,timer要打开。Close
会先关闭ByteStream
再push。
要在push中读ByteStream
之后检查ByteStream
是否is_finished()
。如果是,带上FIN。