Checkpoint0: networking warmup
Networking by hand
在Web browser中访问网页。
接下来用命令手动完成浏览器所做的操作。
tinuvile@LAPTOP-7PVP3HH3:~$ telnet cs144.keithw.org http
Trying 104.196.238.229...
Connected to cs144.keithw.org.
Escape character is '^]'.
^]
telnet> close
Connection closed.这个命令指示telnet程序在我的电脑和cs144.keithw.org电脑间建立一个字节流连接,并访问该电脑上运行的特定服务http。
然后GET会告知服务器URL路径,Host输入主机部分,close以及句末回车再回车告知服务器已经完成HTTP请求。完整的如下:
tinuvile@LAPTOP-7PVP3HH3:~$ telnet cs144.keithw.org http
Trying 104.196.238.229...
Connected to cs144.keithw.org.
Escape character is '^]'.
GET /hello HTTP/1.1
Host: cs144.keithw.org
Connection: close
HTTP/1.1 200 OK
Date: Tue, 22 Apr 2025 10:04:29 GMT
Server: Apache
Last-Modified: Thu, 13 Dec 2018 15:45:29 GMT
ETag: "e-57ce93446cb64"
Accept-Ranges: bytes
Content-Length: 14
Connection: close
Content-Type: text/plain
Hello, CS144!
Connection closed by foreign host.Listening and connecting
这个是作为一个简单服务器的角色。在一个终端窗口中输入:
然后在另一个终端中输入:
这时候第一个终端窗口会出现:
表明已经连接成功了。netcat是服务器端,telnet是客户端。

然后在netcat窗口ctrl+C退出程序,telnet也会立即退出。
Writing a network program using an OS stream socket
这个实验要用到Linux内核提供的stream socket功能,这个功能可以在两台计算机间创建可靠的双向字节流。
实验设计基于Unix套接字API,所以需要在Linux或者WSL环境下完成。我用的是Ubuntu 20.04.6 LTS。
编译源代码。
课程给我们提供了一些编码建议,希望充分利用新特性实现最大程度的安全编程,可查阅C++ Core Guidelines。核心理念是确保每个对象的设计具备尽可能小的公开接口,包含大量内部安全检查机制,难以被误用,并能自主清理资源。具体来说:
避免成对操作,如
malloc/free,new/delete,因为这些操作的后者可能因为函数提前返回或抛出异常而无法执行。建议采用Resource acquisition is initialization的模式(RAII),操作应在对象构造函数中完成,逆向操作则应在析构函数中自动执行。尽量不要使用原始指针,必要时使用智能指针
unique_ptr或shared_ptr。避免使用模板、线程、锁和虚函数。
避免使用C风格字符串
char *str或字符串函数,改用std::string。切勿使用C风格类型转换,必要时使用C++的
static_cast。函数参数传递优先使用常量引用方式,如
const Address & address。所有不需要修改的变量和方法都声明为
const。避免使用全局变量,尽可能为每个变量赋予最小的作用域。
提交作业前运行
cmake --build build --target tidy获取改进建议,并运行cmake --build build --target format保持代码格式一致。
Reading the Minnow support code
公共接口部分阅读util/socket.hh和util/file_descriptor.hh。继承关系为TCPSocket → Socket → FileDescriptor,关键部分列在下面:
file_descriptor.hh
这个类是一个引用计数的文件描述符句柄,用shared_ptr管理FDWrapper,FDWrapper封装了底层的文件描述符。然后这个类将 POSIX 系统调用封装成了 C++ 方法。
socket.hh
Socket继承自FileDescriptor,增加了网络相关的方法,子类TCPSocket、UDPSocket进一步特化。
Writing webget
HTTP 请求是通过 TCP 连接发送的纯文本字节流,write方法将字节流写入文件描述符。
运行测试:
运行cmake --build build --target check_webget通过。
An in-memory reliable byte stream
这个任务需要我们实现字节流功能。这个字节流是有限容量的,写入的数据不能超过当前可用容量。当写入者写入数据时,如果缓冲区已满,只能写入部分数据。读取者可以读取数据,并从缓冲区中移除已读取的部分,这样释放空间,让写入者可以继续写入。同时,写入者可以关闭流,读取者在读取完所有数据后会到达EOF。
首先ByteStream需要维护一个缓冲区,我选用的是std::string。
然后实现Reader和Writer的具体函数,比较简单。
运行测试。
提交前用clang-format统一代码风格。
这样就算完成了。
Last updated