CS144 Lab4 : 组装模块
整体设计

TCP FSM
接收数据:
- 如果接收到了带有
RST标志的段,就要立即进行unclean_shutdown - 如果接收到的段没有
RST标志,将有TCPReceiver来处理这个段的SYN,payload,FIN和seqno。 - 若果这个段的
seqno是无效的,或者TCPReceiver接收这个段失败时,要发送一个空的段给对方
发送数据:
TCPSender将段发送到自己的队列时,TCPConnection就要从TCPSender中取出来放到自己的队列中,在这个过程中如果TCPReceiver的ackno为有效值的话,就要给这些段加上ACK标记,自己的ackno以及window size。TCPConnection通过tick函数获得时间,我们要将时间交给TCPSender的tick函数,让它来进行重传操作。- 重传的次数超过
TCPConfig::MAX_RETX_ATTMPTS的话就要发送一个RST的段。 - 如果
TCPConnection的active为真,这时TCPConnection析构了,就要立即发送一个RST段。
**unclean_shutdown**:
- 收到
RST标志的段,就是unclear_shutdown.
**clean_shutdown**:
完成 4 次挥手。
先收到
FIN的一方,在最后发送完不需要进行等待。先发送
FIN的一方,最后发送ACK后需要等待一定时间。先收到
FIN的一方,在收到对方对自己 发送的FIN的确认ACK后,就立刻关闭了,不在发送其他数据。先发送
FIN的一方通过等待 10 $\times$ 初始超时时间限制 时间来确认对方收到了自己的ACK, 在这段时间里没有重传就结束。
感觉代码有些难写,多次测试不能完全保证每次测试都通过。
TCP 有限状态机

Receiver

Sender

性能优化
使用 gprof 工具分析性能。

可以看到 ByteStream::write , ByteStream::peek_output 和 ByteStream::pop_output 占用了快 90% 的时间,这主要是方法内部实现使用的深拷贝。
实验在 util 提供了 Buffer , BufferList 和 BufferListView 这样的类。
Buffer 的 remove_prefix 方法是常数级别的删除前 n 个字符。Buffer存放的是智能指针,及 size_t 类型的标记来表示字符的开始位置,删除前 n 个字符只需要变动这个标记即可,智能指针指向的内存会随着 Buffer 的析构而释放,在获得性能的同时保持安全。
使用 BufferList 重写 ByteStream 后的性能分析。
