Checkpoint0
# Checkpoint1
本实验需要完成一下几个任务:
fetch a Web page over the Internet
a reliable stream of bytes between a writer and a reader
# Fetch a Web page Manually
telnet 可以创建一个客户端,然后用来和服务器建立连接。
在虚拟机上运行
telnet cs144.keithw.org http并enter
telnet将会使用HTTP协议在本地电脑和服务器 (cs144.keithw.org) 之间打开一个 reliable byte stream。
(可以使用 ctrl+] quit 退出 telnet)输入
GET /hello HTTP/1.1并enter
告知服务器 path part of the URL输入
HOST: cs144.keithw.org并enter
告知服务器 host part of the URL输入
Connection: close并enter
告诉服务器你完成了 HTTP 请求制作,让服务器应答后关闭链接。输入
enter
发送一个空行给服务器,告诉服务器你已经完成了你的 HTTP 请求。运行上面的命令后,服务器会向你发送你在浏览器
https://cs144.keithw.org中看到一样的内容,并且带有一个 HTTP headers。(用来告诉你的浏览器是如何解析这个相应)
HTTP/1.1 200 OK
Date: Mon, 24 Apr 2023 08:39:57 GMT
Server: Apache
Last-Modified: Thu, 13 Dec 2018 15:45:29 GMT
ETag: "e-57ce93446cb64"
Accept-Ranges: bytes
Content-Length: 14
Content-Type: text/plain
Hello, CS144!
2
3
4
5
6
7
8
9
10
# Listing and Connecting
在本机上模拟出 client and server。
在一个终端中使用命令
netcat -v -l -p 9090在本地电脑上创建一个程序并监听 9090 端口。在另一个终端中使用命令
telnet localhost 9090和 9090 端口建立连接。然后在任意一个终端的输入都会在另一个终端中可见。
# Write a Program to Fetch a Web Page
本小节将使用 Linux Kernel 提供的 stream socket 写一个程序来获取网页内容。
stream socket 是操作系统提供的在两台计算及的两个程序程序之间创建可靠双向字节流的方法。socket 像一个 file descriptor (比如 stdin, stdout of I/O stream)。
当两个 socket 建立连接后,写入一个 socket 的字节就会传送到另一个 socket。
在现实生活中,Internet 并不直接提供这种可靠字节流传输的能力,Internet 只提供 best effort 的数据传输。(这种数据也被称之为 Internet datagrams )
每个 datagram 中都含有:
- metadata (包含源地址和目的地址)
- payload data (有效的数据载荷)
因为在数据传输过程中可能会发生:
- lost
- delivered out of order
- delivered with tehe contents altered
- duplicated and delivered more than once
所以就需要操作系统将这种 best effort 的交付方式,转化为 reliable byte streams —— 这就是通过 TCP (Transmission Control Protocol) 实现的
在这个实验中,我们只是简单的使用 OS 已经为我们提供的这种可靠数据传输的能力。使用这种能力写一个程序 webget ,该程序会创建一个 TCP Socket 和 Web Server 进行连接来获取网页信息。(类似于之前使用 telnet 获取网页信息一样)。
# 3.1 获取开始代码
$ git clone https://github.com/cs144/minnow
$ cd minnow
$ mkdir build
$ cd build
$ cmake ..
2
3
4
5
# 3.2 编程规则
本实验的基本思想:
- 确保每个对象都被设计为具有尽可能小的公共接口
- 具有许多内部安全检查 (使用 assert)
- 如果函数 / 类被错误的使用,应该提前警告
- 资源应该在 constructor 中被分配,在 destructor 中被释放 (也就是 RAII,关于更多 RAII 的内容请看的知识库 RAII)
其他:
- 🈲️
malloc()andfree() - 🈲️
newanddelete - 🈲️
raw pointers, useunique_ptrandshared_ptronly when necessary (作者说这些在 CS144 中都不需要) - 避免
templates,threads,locks,virtual functions(作者说这些在 CS144 中都不需要) - 避免 C-style strings and string funcitons (
strlen(), strcpy()) - 🈲️C-style casts (e.g., (FILE *) x). 如果有必要请使用
static_cast(作者说这些在 CS144 中都不需要) - 在进行下一个项目之前使用
cmake --build build --target tidy来查看 code 改善建议,使用cmake --build build --target format将代码格式化为标准格式
下面是在我这里日常必须必须做到的: - Prefer passing function arguments by const reference (这个在我这里是必须,坚决不
pass by value) - Make every variable const unless it needs to be mutated
- Make every method const unless it needs to mutate the object
- Avoid global variables, and give every variable the smallest scope possible
# 3.3 阅读相关代码
初始代码已经将有关 socket 的 C 函数都包装到了 Modern C++ 的类中。在开始实验前,需要仔细阅读 util/socket.hh and util/file_descriptor.hh 中 public 的成员函数。
注意
Socket 的类型是 FileDescriptor , TCPSocket 的类型是 Socket
所以说明 TCPSocket 的类型是 FileDescriptor?
# 实现 webget
(在 ./apps/webget.cc 中完成)
- 使用 TCPSocket 和 Address 类