CS144-lab6
实现route.cc这个lab是实现路由器,路由转发的功能,需要维护一个路由转发表,通过目标IP地址与路由转发表中存储的IP地址进行最长前缀匹配来决定数据报要从路由器上面的哪一个网络接口Network Interface发出。
代码route.hh
class Router {
.....
//! The router's collection of network interfaces
struct Table {
const uint32_t route_prefix;
const uint8_t prefix_length;
const std::optional<Address> next_hop;
const size_t interface_num;
};
std::vector<AsyncNetworkInterface> _interfaces{};
std::vector<Ta
CS144-lab5
实现Network Interface网络接口Network Interface是网络层和链路层链接的桥梁,它的作用就是将网络层传下来的Internet datagrams封装成链路层的Ethernet frames,然后将封装好的Ethernet frames发出。
封装Ethernet frames想将Internet datagrams封装成Ethernet frames我们需要知道Destination Mac Address和Source Mac Address 和 EtherType。
Source Mac Address : 本机的Mac地址。
Destination Mac Address : 目标主机的Mac地址会被存储到本机的目标IP和目标Mac地址的映射数据结构中,如果本机维护的这个数据结构不存在目标IP的Mac地址,那么我们就需要使用ARP协议向局域网中的其他主机询问目标IP的Mac地址。(APR协议的细节:Address Resolution Protocol)
EtherType : 表示上层Internet datagrames使用的协议类型,lab5中
CS144-lab4
实现TCPConnectionTCPConnection实际上就是结合TCPReceiver和TCPSender结合实现一个TCP的有限状态机(TCP Finite State Machine (FSM)),也就是实现下面这一张实际运行的逻辑图实现TCPConnection我修改了TCPReceiver和TCPSender一些接口的返回值例如将返回void修改成返回bool
详细的FSM可以看这个网页: TCP Finite State Machine
其次就是研究透彻tcp_state.cc,这个文件中描述了TCPConnection处于某个状态的时候,TCPSender和TCPReceiver应该处于什么状态,例如:当TCPConnection处于LISTEN状态的时候,TCPSender和TCPReceiver应该分别处于CLOSED和LISTEN状态,(TCPSender和TCPReceiver)的状态在lab2和lab3中有描述。
TCPConnection.hh
...
//为实现TCPConnection而增添的代码
bool _active{true&
CS144-lab3
实现TCPSender这个lab有几个难点,分别是:
TCP中会维护好几种状态:
CLOSE: SYN还没有被发送
SYN_SENT: SYN被发送了但是没有收到对应的ACK
SYN_ACKED: 正常状态,可以利用sender来通信了
SYN_ACKED_ASLO: sender已经发送完所以的字节流了,但是还没有发生FIN。
FIN_SENT: FIN已经被发送,但是还没有收到对应的ACK
FIN_ACKED: sender已经完成所以的任务。
TCPSender使用的是累计确认的协议,也就是说如果收到合法的ACK,那么ACK之前的所有已经发送segments已经被成功接受。(如果收到的ACK大于我还未发送的Sequence Number那就是非法的ACK)
timer的开启,重启,关闭的时机。在做这个是lab之前我一直以为是给每一个发出的segments安装一个timer,当segments超时的时候重发,但是看了huangrt01大佬的代码后,发现在这个lab中timer,timer记录的是在RTO时间内有没有收到合法的ACK,如果没有收到合法的ACK,那么就需要重传
CS144-lab2
实现wrapping_integers.cc1.wrapping_integers.cc这个文件是干什么的呢?wrapping_integers.cc主要做两件事情,一是将64位表示的数包装成32位表示的数。二是将32位的数解包装还原为64位的数。至于为什么要这么做我们下面解释。
2.为什么要将64位数转化成32位数,32位数还原为64位数呢?因为TCP的Sequence Number和Acknowledgement Number是32位的,最多最多也就只能表示4G大小数据的传输,如果将32位其转化为64位后,就可以表示2^64-1这么大的空间(目前看说几乎是无限大),那么怎么转化呢?我们用Initial Sequence Number = 0,来举例,我们称呼转化后的64位的数字为Absolute Sequence Number 。当TCP传输的数据小于4G的时候(这里假设Initial Sequence Number = 0),TCP的Sequence Number 与 Absolute Sequence Number相同,当TCP传输的数据大于4G后,TCP中的Sequence
CS144-lab1
实现 stream reassembly
什么是 stream reassembly ?stream reassembly 是一个字符流重组器 , 主要的功能是将传入的没一份打乱的字符流重新组合形成原来的有序的字符流。
实现 stream reassemblystream reassembly 被包装成一个类,也就是lab1要实现的StreamReassembler类 。
为了实现这个类的功能,我在类中添加了一下的一些变量和函数。
class StreamReassembler {
private:
size_t expected_index;
bool _eof_appear_sign;
size_t _eof_index ;
std::map<size_t,std::string> window;
void write_substring();
void insert_pair(const std::string &data,const size_t inde
CS144-lab0
实现webget.cc实现webget.cc实际上就是补充get_URL()函数。这里比较值得注意的是通过套接字与采用http协议的服务器沟通的语法是这样的:
GET /hello HTTP/1.1 //注意这里换行符号为\r\n
Host: cs144.keithw.org
Connection: close
在程序上表现为:"GET " + path + " " + "HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n"
void get_URL(const string &host, const string &path) {
TCPSocket sock1;
Address addr = Address(host, "http");
sock1.connect(addr);
sock1.write("GET " +
The rule of Three/Five
引用:
Rule of three (C++ programming))
C++11: The Rule of the Big Five
IntroductionThe Rule of Three/Five (三法则/五法则)是为了编写异常安全代码(Exception-safe code)和为了资源管理而提出的经验法则。
The Rule of Three首先介绍编译器会自动生成的三个特殊的成员函数(Special member funtions)
Desturctor (析构函数)
Copy Constructor (拷贝构造函数)
Copy assignment operator (拷贝赋值运算符)
三法则规定:如果类中定义了以下三个特殊的成员函数的其中一个,则这个应该显式的定义所有的三个特殊的成员函数。因为默认生成的三个函数通常不能满足我们的使用要求。
默认生成的Copy Constructor和Copy assignment operator执行的是浅拷贝(Shallow Copy)。而我们的类中如果存在指针这类的成员变量,使用默认生成的这两个函数,可能会引起内存泄漏及
lvalue and rvalue
如果有小伙伴看到我的文章的话,建议优先去看下面的这些文章,因为我写的质量不及下面文章的十分之一(哭脸)
Rvalue References: C++0x Features in VC10, Part 2
What is move semantics?
What is the copy-and-swap idiom?
lvalue VS rvalue, rvalue Reference, and Move Semantics in C++
C++笔记 · 右值引用,移动语义,移动构造函数和移动赋值运算符
还有这些视频:
Move Semantics in C++
Advanced C++: Understanding rvalue and lvalue
lvalue and rvalue在C++中,每一个表达式都是由lvalue和rvalue组成.
Example
int i = 0; /*i为lvalue,0为rvalue*/
int a = i+1; /*a为lvalue,i+1是rvalue*/
1 /*1为rvalue*/
lvalue
PA3.2必答题
必答题-hello程序是什么, 它从而何来, 要到哪里去到此为止, PA中的所有组件已经全部亮相了, 整个计算机系统也开始趋于完整. 你也已经在这个自己创造的计算机系统上跑起了hello这个第一个还说得过去的用户程序 (dummy是给大家热身用的, 不算), 好消息是, 我们已经距离运行仙剑奇侠传不远了(下一个阶段就是啦).
不过按照PA的传统, 光是跑起来还是不够的, 你还要明白它究竟怎么跑起来才行. 于是来回答这道必答题吧:
我们知道navy-apps/tests/hello/hello.c只是一个C源文件, 它会被编译链接成一个ELF文件. 那么, hello程序一开始在哪里? 它是怎么出现内存中的? 为什么会出现在目前的内存位置? 它的第一条指令在哪里? 究竟是怎么执行到它的第一条指令的? hello程序在不断地打印字符串, 每一个字符又是经历了什么才会最终出现在终端上?
上面一口气问了很多问题, 我们想说的是, 这其中蕴含着非常多需要你理解的细节. 我们希望你能够认真整理其中涉及的每一行代码, 然后用自己的语言融会贯通地把这个过程的理解描述清楚, 而不是机械地分点回答这几个问