CS144 是 MIT 的计算机网络课程。其 Project 主要目标是根据实验指导,用 C++ 循序渐进地搭建出整个 TCP/IP 协议栈。该 Project 包含了 Network Layer 和 Transport Layer 的知识,能够让学生从代码的角度理解实现细节。下文内容主要关于 CS144 的 Lab4。
对于上面的状态图,事件描述的左边为接收数据段,而右边为发送数据段。举个例子:若机器当前状态为 LISTEN,在接收到 SYN 数据段时,则会发送 SYN+ACK 数据段,并将状态切换成 SYN RECEIVED。
下面是在 CS144 中,TCP Connection 对应的 Receiver 和 Sender 的状态表:
(其中,linger
和 active
的默认值为 ture)
Connection | Receiver | Sender |
---|---|---|
LISTEN | LISTEN | CLOSED |
SYN_SENT | LISTEN | SYN_SENT |
SYN_RCVD | SYN_RECV | SYN_SENT |
ESTABLISHED | SYN_RECV | SYN_ACKED |
FIN_WAIT_1 | SYN_RECV | FIN_SENT |
CLOSE_WAIT | FIN_RECV | SYN_ACKED linger(false) |
LAST_ACK | FIN_RECV | FIN_SENT linger(false) |
CLOSING | FIN_RECV | FIN_SENT |
FIN_WAIT_2 | SYN_RECV | FIN_ACKED |
TIME_WAIT | FIN_RECV | FIN_ACKED |
RESET | ERROR | ERROR linger(false) active(false) |
CLOSED | FIN_RECV | FIN_ACKED linger(false) active(false) |
不同于主动关闭和被动关闭的策略,当连接双方同时发送 fin 时,二者都会进入 CLOSING 状态,并等待对方发送的 ack 包。
每一个 TCPConnection 会作为一个实体与另外一个 TCPConnection 进行交互。
active
和 _linger_after_streams_finish
active
和 linger_after_streams_finish
作为实验中给出的两个 TCP Connection 的参数,在刚开始并不易理解其作用。同时二者均为决定当前状态的重要参数,故在实验中,需要对这两个变量有清晰的定位以及及时设置的意识。
active
的作用是标志当前 TCP Connection 是否 可用/活跃。在其被创建时,active
默认被置为 true,则此时处于 LISTEN
状态。当且仅当状态为 RESET
或 CLOSED
时,active == false
linger_after_streams_finish
在释放连接时,主动方和被动方分别采取被主动关闭和被动关闭的策略,通过 _linger_after_streams_finish
进行区分。
当 _linger_after_streams_finish = true
时,TCP Connection 在发送完最后一个 ACK 包后,会等待 10*_cfg.rt_timeout
时间再关闭,被称为 主动关闭 ;相反,_linger_after_streams_finish = false
时,为 被动关闭,TCP Connection 会在发送 fin 并接收到对应的 ack 后关闭连接。
end_input_stream
: sender 数据流输入结束tick
: 时间记录write
: 写入 sender 待传输的数据inbound_stream
: 传输 receiver 接收到的数据flowchart LR Application-Layer subgraph Transport-Layer sender receiver end Application-Layer --> |write| sender Application-Layer --> |end_input_stream| sender receiver --> |inbound_stream| Application-Layer Network-Layer Network-Layer --> |datagram|sender receiver --> |datagram|Network-Layer
CS144 实验环境的配置有多种选择,一种是使用官方提供的虚拟机,也可以在自己的 wsl 等本地环境中进行配置。
在 WSL 下,网络通信有些问题,会导致 wget
超时。
# 加载编译环境
$ sudo apt-get install doxygen
$ sudo apt-get install libpcap-dev
本次实验是计算机网络课改班的 Lab2、Lab3、Lab4、Lab5。其中 Lab2 做了环境配置和 wget 代码的撰写,Lab3 完成了网络层的功能,Lab4 完成了传输层 TCP 的 Receiver 以及 Sender,Lab5 的 TCP Connection 将 Lab4 的功能模块连了起来并能够进行真实的网络通信,为 Lab2 的 wget 提供算法支撑。
网上许多同学评价 CS144 Lab5 TCP Connection 是最难实现的,因为它涉及前面的诸多内容,之前没发现的 bug 在这次实验中可能会被发现。在指导手册中,作者建议学生不要去看测试样例的源码,因为它会让我们进行面向数据测试点的 debug,而不是整体逻辑上自洽的修改虽然大部分的 bug 我也是面向测试点才发现的。这里也给出几个 debug 的建议:
这次实验还是颇有收获的,具体列在下面: