CS144

Abstract

CS144 是 MIT 的计算机网络课程。其 Project 主要目标是根据实验指导,用 C++ 循序渐进地搭建出整个 TCP/IP 协议栈。该 Project 包含了 Network LayerTransport Layer 的知识,能够让学生从代码的角度理解实现细节。下文内容主要关于 CS144 的 Lab4。

TCP 协议的状态机

对于上面的状态图,事件描述的左边为接收数据段,而右边为发送数据段。举个例子:若机器当前状态为 LISTEN,在接收到 SYN 数据段时,则会发送 SYN+ACK 数据段,并将状态切换成 SYN RECEIVED。

下面是在 CS144 中,TCP Connection 对应的 Receiver 和 Sender 的状态表:
(其中,lingeractive 的默认值为 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)
CLOSING 状态

不同于主动关闭和被动关闭的策略,当连接双方同时发送 fin 时,二者都会进入 CLOSING 状态,并等待对方发送的 ack 包。

TCP Conection

每一个 TCPConnection 会作为一个实体与另外一个 TCPConnection 进行交互。

active / linger_after_streams_finish

为什么要讲 active_linger_after_streams_finish

activelinger_after_streams_finish 作为实验中给出的两个 TCP Connection 的参数,在刚开始并不易理解其作用。同时二者均为决定当前状态的重要参数,故在实验中,需要对这两个变量有清晰的定位以及及时设置的意识。

active

active 的作用是标志当前 TCP Connection 是否 可用/活跃。在其被创建时,active 默认被置为 true,则此时处于 LISTEN 状态。当且仅当状态为 RESETCLOSED 时,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 后关闭连接。

与其他层的交互

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 的建议:

这次实验还是颇有收获的,具体列在下面:

参考资料