CS144-Lab2实验笔记
实验简介
这个实验主要完成的是,TCP接受端应该如何工作,才能正确地将TCP Payload交付给socket的问题。
CS144 Lab实现的是这个场景:NIC从链路上收到MAC数据包,交给kernel;kernel解析MAC头后,将这个包传给虚拟的tun设备。CS144 Lab中的其他辅助函数从tun设备中读取IP包,拆包后将完整TCP报文交给tcp_receiver/tcp_sender
这两个我们自己写的程序。
tcp_sender
负责:解析包头、将Payload交付给socket,这样应用程序就能从socket中读取数据了。
实验思路
1. 序列号与绝对序列号的相互转换
对于这个问题不必考虑SYN/FIN是否计算的问题,因为二者都包含了SYN/FIN
1.1 收到的TCP Header中seqno
是对端表示其TCP报文内携带的Payload的序列号。
将收到的第一个包(SYN包)携带的
seqno
称为“起始序列号”,通常是一个32位随机值之后收到的包的
seqno
则表示当前包携带的Payload相对于“起始序列号”的偏移
1.2 绝对序列号指的是当前包的seqno
相对于起始序列号,实际的偏移
- 这样就可以知道当前包Payload在乱序字节流里面的起始index了(绝对序列号转到stream index的时候才考虑忽略SYN的问题)
1.3 绝对序列号转换为序列号
- 绝对序列号加上起始序列号对2^32取模即可
1.4 序列号转换为绝对序列号
(TODO)
2. 实现TCP接收端
2.1 接收端根据收到TCP包头的seqno + SYN_FLAG + FIN_FLAG + Payload
这几个字段,决定本端的ackno + win_size
如下图所示
2.2 根据当前包的seqno
得到绝对序列号,再得到stream index
- 将Payload按照
stream index
推到乱序字节流中。乱序如何重组为有序的问题Lab1中已经实现了。
2.3 向对端响应ackno
ackno
指的是本端期望收到下一个数据包的序列号。也就是已经收到的数据的有序字节长度加1
2.4 向对端响应window_size
window_size
指的是本端的接受窗口大小,对端按照收到的窗口大小来填充payload的字节数。具体到实验就是接收端乱序字节流的最大容量减去有序字节流中的字节数(已经重组但未被应用程序读取这部分)。
实现
TCPReceiver类内新增一些变量
1 |
|
具体的实现
1 |
|
CS144-Lab2实验笔记
https://gwzlchn.github.io/202205/cs144-lab2/