总耗时:65h 约17天

实验官网

感恩

总结

本实验总体思维和代码上的难度还是不难的(至少比xv6简单),我认为其难点主要集中在TCP协议本身就很复杂很多的细节问题,以及需要我们有一种面向测试用例编程、直面自己往日写过的屎山的勇气(。

下面,我将对本实验的完成情况即心得进行一个总结,也算是本篇博客/本次实验的一个导读

类似于这样的块引用中的部分是我自认为的精华部分

本实验对TCP-IP-ETH协议栈的实验是自顶向下的,其中对TCP协议的实现是由内而外的。

后者很容易导致,在对TCP协议的实现中,当你写完了lab0-3,你还是不知道自己到底写了个啥,以及TCP又究竟怎么通过你写的那几个类run起来。直到lab4结束,你完成了对TCP状态机的组织,并且出于debug目的钻研过部分socket的代码、熟悉了(其实差不多已经背下来了)TCP的三握手四挥手的过程,至此你才会对TCP的实现有较为清晰的理解。这个过程很痛苦,但是也真的非常爽。

关于TCP状态机的理解总结,请参见Lab4 TCPConnection——心得——总结:状态机部分。

然而,实现了TCP协议之后,我们还是不知道,在TCPConnection中发送的数据包,又是如何到达网络上的另一个host处的,我们究竟又写了个啥。

这时,官方贴心地为我们指了条明路:它告诉我们,我们在lab0-4实现的是TCP-IP协议栈,其中运输层和网络层由用户实现,其他更底层则由内核实现,二者通过操作系统提供的TUN接口进行交互。也即,我们之前实现的是用户态TCP协议!而我们接下来的学习目标,就是从内核中再夺走一些权力:数据链路层也要由我们自己实现!

关于此处的TCP-IP架构等,请参见Lab5 NetworkInterface——Overview——承上启下

故而,接下来,我们将实现用户态的TCP-IP-ETH协议栈。在lab5,我们将目光投向TCP层以下的数据链路层(网络层官方已经帮我们实现了),实现ETH协议和ARP协议;在lab6,我们则需要实现路由查找的功能。

至此,所有实验已经结束。写完了上述实验,我们对协议栈已经具有了很深刻的了解,对TCP—IP—ETH—TAN—Internet—TAN—ETH—IP—TCP的这个数据传输过程也已经是懂王了。

然而,我们在TCPConnection,只知道会有好心人,在上层app有数据传进来的时候调用write、在下层协议栈有segment传进来的时候调用segment_received、取出_segment_out的segment向底层协议栈发送、读走outputstream的内容。但是这个所谓的“好心人”具体是怎么做到的,怎么实现的,我们一概不知。

答案是,这个所谓的“好心人”,其实就是我们的TCPSpongeSocket。它向上将协议栈与上层app连接,向下又将协议栈与TAN接口结合。

发送数据时,数据流向:上层app→(通过TCPSpongeSocketTCPConnection→(通过write方法)ByteStreamTCPSender→(通过从_sender.segments_out读)TCPConnection→(通过TCPSpongeSocket的adapter)TAN

接收数据时,数据流向:TAN→(通过TCPSpongeSocket的adapter)TCPConnectionTCPReceiver→(中间经过StreamAssemblerBYteStream→(通过TCPSpongeSocket读)上层app

TCPSpongeSocket的adapter中:TCPsegment←→IP数据报←→ETH帧

至于ETH帧进入TAN之后的过程?在xv6的网卡驱动那一节我们事实上已经实现过了!

CS144TCPSocketFullStackTCPSokect都继承自TCPSpongeSocketTCPSpongeSocket通过一个包装了操作系统提供的socket的包装类_thread_data来与上层app进行交互,通过adapter_datagram_adapter来与协议栈进行交互(adapter本质上也是调用了操作系统的TUN/TAN接口)。

由于_thread_data_datagram_adapter本质上都是文件描述符【牛逼吧】,因而,TCPSpongeSocket需要跟上下层进行交互的需求,就可以通过操作系统提供的POLL机制来实现,也即,app←→TCP、TCP←→协议栈的这四种数据交互情况,都用事件监听来实现!当有datagram需要传入的时候会在事件处理体之中调用我们实现的tcp协议的segment_receive,同样在tcp的segement_out非空时将其发送。这样就能做到“及时”“高效”了。

关于此处TCPSpongeSocket的事件监听机制以及其它实现细节,详见其它的对…——Socket实现——TCPSpongeSocket

至此以来,我们的协议栈才算真正完整了。

Lab0

Lab1 StreamReassembler

Lab2 TCPReceiver

Lab3 TCPSender

Lab4 TCPConnection

Lab5 NetworkInterface

Lab6 Router

其他的对实验未涉及的思考