总耗时: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→(通过
TCPSpongeSocket
)TCPConnection
→(通过write
方法)ByteStream
→TCPSender
→(通过从_sender.segments_out
读)TCPConnection
→(通过TCPSpongeSocket
的adapter)TAN
接收数据时,数据流向:
TAN
→(通过TCPSpongeSocket
的adapter)TCPConnection
→TCPReceiver
→(中间经过StreamAssembler
)BYteStream
→(通过TCPSpongeSocket
读)上层app在
TCPSpongeSocket
的adapter中:TCPsegment←→IP数据报←→ETH帧至于ETH帧进入TAN之后的过程?在xv6的网卡驱动那一节我们事实上已经实现过了!
CS144TCPSocket
和FullStackTCPSokect
都继承自TCPSpongeSocket
。TCPSpongeSocket
通过一个包装了操作系统提供的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
至此以来,我们的协议栈才算真正完整了。