Kiprey / Kiprey.github.io

This is Kiprey‘s Blog.
https://kiprey.github.io/
4 stars 3 forks source link

CS144计算机网络 Lab4 | Kiprey's Blog #74

Open Kiprey opened 2 years ago

Kiprey commented 2 years ago

https://kiprey.github.io/2021/11/cs144-lab4/

puppet12306 commented 2 years ago

实验把官方的状态机分成了sender和receiver两个部分,两者的映射又需要分别调用sender和receiver的函数之后才能同步上,导致实验异常头痛,参考了你的代码又翻看state.h文件半天才搞明白

chang-you-ren8 commented 1 year ago

我进行性能测试的时候throughput 是0.12Gbit/s, 0.12Gbit/s,请问有关于性能调优的建议吗?这个性能测试和我本地的网络有关系吗?

chang-you-ren8 commented 1 year ago

和自己的电脑某方面的性能有关吗?

Kiprey commented 1 year ago

我进行性能测试的时候throughput 是0.12Gbit/s, 0.12Gbit/s,请问有关于性能调优的建议吗?这个性能测试和我本地的网络有关系吗?

和本地网络应该无关,编译的时候应该设置为 release 版本来编译。

chang-you-ren8 commented 1 year ago

我认为不管_receiver实现的多鲁棒segemt_received函数都需要判断segment是否合法吧?如果我发送一个segment 其RST置位了,但是其是不合法的segment, 那么这个连接也会被终止吧?

Kiprey commented 1 year ago

我认为不管_receiver实现的多鲁棒segemt_received函数都需要判断segment是否合法吧?如果我发送一个segment 其RST置位了,但是其是不合法的segment, 那么这个连接也会被终止吧?

不合法的 segment 指的是?如果说是指 segment seqno 等异常情况,那 receiver 并不会将这个 segments 放到自己的缓冲区里去。不过有一点是对的,receiver 并没有把 segments 的异常情况报告给上层 connection ,这意味着 一个 错误的 segments RST 会被 connection 错误确认

目前实现的这个版本还是有些安全问题。T_T

derecknowayback commented 1 year ago

K大,这里tshark报错 “没有找到 144tun device” ,但是我按照实验给的脚本粘贴的,您有遇到过类似的问题吗

Kiprey commented 1 year ago

@derecknowayback K大,这里tshark报错 “没有找到 144tun device” ,但是我按照实验给的脚本粘贴的,您有遇到过类似的问题吗

需要先执行 make check_lab4 来创建 tun/tap 虚拟网络设备。

derecknowayback commented 1 year ago

@Kiprey

@derecknowayback K大,这里tshark报错 “没有找到 144tun device” ,但是我按照实验给的脚本粘贴的,您有遇到过类似的问题吗

需要先执行 make check_lab4 来创建 tun/tap 虚拟网络设备。

嗷!谢谢!后续测试也是先make check_lab4 然后手速快快的开启wireshark抓包是吗

Kiprey commented 1 year ago

@derecknowayback

@Kiprey

@derecknowayback K大,这里tshark报错 “没有找到 144tun device” ,但是我按照实验给的脚本粘贴的,您有遇到过类似的问题吗

需要先执行 make check_lab4 来创建 tun/tap 虚拟网络设备。

嗷!谢谢!后续测试也是先make check_lab4 然后手速快快的开启wireshark抓包是吗

make check_lab4 建立虚拟网卡完成后这个虚拟网卡会一直存在,不用担心它会消失。(时间有些许久远,我有点忘记了)

derecknowayback commented 1 year ago

@Kiprey

@derecknowayback

@Kiprey

@derecknowayback K大,这里tshark报错 “没有找到 144tun device” ,但是我按照实验给的脚本粘贴的,您有遇到过类似的问题吗

需要先执行 make check_lab4 来创建 tun/tap 虚拟网络设备。

嗷!谢谢!后续测试也是先make check_lab4 然后手速快快的开启wireshark抓包是吗

make check_lab4 建立虚拟网卡完成后这个虚拟网卡会一直存在,不用担心它会消失。(时间有些许久远,我有点忘记了)

好的好的!太感谢您了!感谢感谢!

derecknowayback commented 1 year ago

K大,不好意思,又麻烦你了。我也出现了文中 "tun tap"错误的情况,按照您说的注释掉了,但是在 发送完之后,server端显示了 "new connection"建立成功,client端却一直是 "debug : ip地址... done" ,并没有出现文档里的 "Successfully connected to" , 问了同学他们也说连接不成功。我自己搜过了,也看了测试的那个socket.cc,没有什么头绪,您有想法吗

Kiprey commented 1 year ago

@derecknowayback K大,不好意思,又麻烦你了。我也出现了文中 "tun tap"错误的情况,按照您说的注释掉了,但是在 发送完之后,server端显示了 "new connection"建立成功,client端却一直是 "debug : ip地址... done" ,并没有出现文档里的 "Successfully connected to" , 问了同学他们也说连接不成功。我自己搜过了,也看了测试的那个socket.cc,没有什么头绪,您有想法吗

细节的东西我已经记不太清了,只能多翻翻源码找找问题了(捂脸

derecknowayback commented 1 year ago

@Kiprey

@derecknowayback K大,不好意思,又麻烦你了。我也出现了文中 "tun tap"错误的情况,按照您说的注释掉了,但是在 发送完之后,server端显示了 "new connection"建立成功,client端却一直是 "debug : ip地址... done" ,并没有出现文档里的 "Successfully connected to" , 问了同学他们也说连接不成功。我自己搜过了,也看了测试的那个socket.cc,没有什么头绪,您有想法吗

细节的东西我已经记不太清了,只能多翻翻源码找找问题了(捂脸

好好,谢谢您了!(呜呜呜很感谢很感谢!)

Hoooao commented 1 year ago

tql

EricPengShuai commented 1 year ago

K 大,想问问 ./apps/tcp_ipv4 -l 169.254.144.9 9090 这个 地址 169.254.144.9 是固定的吗,为啥我这样运行之后出现DEBUG: Listening for incoming connection... new connection from 0.0.0.0:0 然后直接 finish,另外我试了试本机的地址也是这样

Kiprey commented 1 year ago

@EricPengShuai K 大,想问问 ./apps/tcp_ipv4 -l 169.254.144.9 9090 这个 地址 169.254.144.9 是固定的吗,为啥我这样运行之后出现DEBUG: Listening for incoming connection... new connection from 0.0.0.0:0 然后直接 finish,另外我试了试本机的地址也是这样

这几天有点忙忘记回复了,这个地址应该不是固定的,只要是在这个虚拟网卡所管辖的网段内的 IP 应该就行。可以直接在代码中全局搜索 169.254 ,看看所搜到的关于发包收包的相关代码。

从输出信息中得知的是,它在启动监听后立即收到了一个来自本机所发起的连接。有可能是网络环境比较复杂,可以尝试更换端口为一个非常规端口(比如随便一个大号端口 23333)来试试。

注:169.254.144.9 实际上也是你的本机 IP,只是这个 IP 是本机在虚拟网卡上的 IP。指定监听这个虚拟 IP 的目的是为了不监听到那些发往本机 9090 端口但是 IP 不为这个虚拟网卡IP的连接。

时隔快两年了,手头上已经没有了这套实验的相关环境,因此一些细节性的问题可能就没法快速测试,只能凭借一点记忆和经验加上阅读代码连蒙带猜的回答了(捂脸),解答的一些内容可能不一定准确,一定要自己验证一下哦。

bsg666 commented 1 year ago

博主你好,我的tun144和tun155网卡之间总是不能连接上,所以导致后面的测试全都失败了,即使用你的代码也会失败,请问能给点建议吗

Kiprey commented 1 year ago

@bsg666 博主你好,我的tun144和tun155网卡之间总是不能连接上,所以导致后面的测试全都失败了,即使用你的代码也会失败,请问能给点建议吗

这个没有别的捷径了我感觉,只能先试着把两个虚拟网卡之间的通信打通。可以试试卸载删除掉之前安装的 tun144 145 网卡然后重新安装试试......

bsg666 commented 1 year ago

@Kiprey

@bsg666 博主你好,我的tun144和tun155网卡之间总是不能连接上,所以导致后面的测试全都失败了,即使用你的代码也会失败,请问能给点建议吗

这个没有别的捷径了我感觉,只能先试着把两个虚拟网卡之间的通信打通。可以试试卸载删除掉之前安装的 tun144 145 网卡然后重新安装试试......

好的,感谢!那我是用make check_lab4 这条指令去自动生成网卡还是去找找其它办法生成网卡呢?

Kiprey commented 1 year ago

@bsg666

@Kiprey

@bsg666 博主你好,我的tun144和tun155网卡之间总是不能连接上,所以导致后面的测试全都失败了,即使用你的代码也会失败,请问能给点建议吗

这个没有别的捷径了我感觉,只能先试着把两个虚拟网卡之间的通信打通。可以试试卸载删除掉之前安装的 tun144 145 网卡然后重新安装试试......

好的,感谢!那我是用make check_lab4 这条指令去自动生成网卡还是去找找其它办法生成网卡呢?

都可以,make check_lab4 内部也会调用一个 shell 脚本来安装网卡,你也可以手动执行这个脚本来完成安装。

wgl-wwm commented 1 year ago

大佬你好,我的tun144和tun145两张虚拟网卡之间似乎无法进行通信,这使得后面的测试样例全挂掉了,请问我应该如何打通两张网卡呢(另外两张虚拟网卡的destination指向的是其本身的ip地址, 比如tun144的ip地址是169.254.144.1, destination也是这个ip, 这样不是环回了吗?)

Kiprey commented 1 year ago

@wgl-wwm 大佬你好,我的tun144和tun145两张虚拟网卡之间似乎无法进行通信,这使得后面的测试样例全挂掉了,请问我应该如何打通两张网卡呢(另外两张虚拟网卡的destination指向的是其本身的ip地址, 比如tun144的ip地址是169.254.144.1, destination也是这个ip, 这样不是环回了吗?)

我也没有什么特别好用的方法,个人感觉只能先试试删除或者解除之前注册的虚拟网卡,然后重新注册虚拟网卡再试试。

wgl-wwm commented 1 year ago

@Kiprey

@wgl-wwm 大佬你好,我的tun144和tun145两张虚拟网卡之间似乎无法进行通信,这使得后面的测试样例全挂掉了,请问我应该如何打通两张网卡呢(另外两张虚拟网卡的destination指向的是其本身的ip地址, 比如tun144的ip地址是169.254.144.1, destination也是这个ip, 这样不是环回了吗?)

我也没有什么特别好用的方法,个人感觉只能先试试删除或者解除之前注册的虚拟网卡,然后重新注册虚拟网卡再试试。

感谢回复,不知道为什么突然就好了hhh

bsg666 commented 1 year ago

博主,要实现与真实服务器通信,最后把TCPSocket换成CS144Socket的意思就是我们把内核协议栈换成了我们自己实现的协议栈了吗?这样理解对吗

Kiprey commented 1 year ago

@bsg666 博主,要实现与真实服务器通信,最后把TCPSocket换成CS144Socket的意思就是我们把内核协议栈换成了我们自己实现的协议栈了吗?这样理解对吗

严格意义上讲不对。无论是 TCPSocket 还是 CS144Socket ,它们都是用 tuntap 技术来直接把 TCP 报文(如果我没记错的话)直接注入进网络设备,而不走内核协议栈。

但 TCPSocket 是已经实现完备的代码,而 CS144Socket 是我们自己实现的代码。从 TCPSocket 换成 CS144Socket 其实就相当于控制变量,在原先 TCPSocket 能跑通并与真实世界交互成功的情况下,通过只更换所实现的 TCP 协议来达到测试 CS144Socket 功能的目的。

bsg666 commented 1 year ago

@Kiprey

@bsg666 博主,要实现与真实服务器通信,最后把TCPSocket换成CS144Socket的意思就是我们把内核协议栈换成了我们自己实现的协议栈了吗?这样理解对吗

严格意义上讲不对。无论是 TCPSocket 还是 CS144Socket ,它们都是用 tuntap 技术来直接把 TCP 报文(如果我没记错的话)直接注入进网络设备,而不走内核协议栈。

但 TCPSocket 是已经实现完备的代码,而 CS144Socket 是我们自己实现的代码。从 TCPSocket 换成 CS144Socket 其实就相当于控制变量,在原先 TCPSocket 能跑通并与真实世界交互成功的情况下,通过只更换所实现的 TCP 协议来达到测试 CS144Socket 功能的目的。

可是文章里知乎链接: tun/tap技术里面说的是tun设备里的数据还会发到用户程序里面,然后再通过socket发到内核协议栈,是我理解有问题吗?

Kiprey commented 1 year ago

@bsg666

@Kiprey

@bsg666 博主,要实现与真实服务器通信,最后把TCPSocket换成CS144Socket的意思就是我们把内核协议栈换成了我们自己实现的协议栈了吗?这样理解对吗

严格意义上讲不对。无论是 TCPSocket 还是 CS144Socket ,它们都是用 tuntap 技术来直接把 TCP 报文(如果我没记错的话)直接注入进网络设备,而不走内核协议栈。

但 TCPSocket 是已经实现完备的代码,而 CS144Socket 是我们自己实现的代码。从 TCPSocket 换成 CS144Socket 其实就相当于控制变量,在原先 TCPSocket 能跑通并与真实世界交互成功的情况下,通过只更换所实现的 TCP 协议来达到测试 CS144Socket 功能的目的。

可是文章里知乎链接: tun/tap技术里面说的是tun设备里的数据还会发到用户程序里面,然后再通过socket发到内核协议栈,是我理解有问题吗?

那就是我记错了,感谢纠错!我复习了一下文章和代码,CS144 所实现的 TCPSocket 类实际上就是支持了 TCP 和 IP 协议这这两层。只不过 IP 协议这一层 CS144 已经通过 TCPOverIPv4OverTunFdAdapter 等类来模拟好了,因此我们只要模拟 TCP 层就好。

EricPengShuai commented 1 year ago

@Kiprey K 大,想确认一个问题,不管使用 TCPSocket 还是 CS144Socket 来实现传输,其底层是不是都走内核 tcp 的发送和接收?所以我们所做的工作是不是只在应用层面上完成所谓的乱序重组以及超时重传等功能呢

Kiprey commented 1 year ago

@EricPengShuai

@Kiprey K 大,想确认一个问题,不管使用 TCPSocket 还是 CS144Socket 来实现传输,其底层是不是都走内核 tcp 的发送和接收?所以我们所做的工作是不是只在应用层面上完成所谓的乱序重组以及超时重传等功能呢

不对吧, tun/tab 机制就是用来直接替换掉内核栈上的 TCP/IP 协议。如果只是基于应用层上做那就完全用不上 tun/tab 了,这个机制可是实打实的会创建新虚拟网卡的。

Kiprey commented 1 year ago

@EricPengShuai

@Kiprey K 大,想确认一个问题,不管使用 TCPSocket 还是 CS144Socket 来实现传输,其底层是不是都走内核 tcp 的发送和接收?所以我们所做的工作是不是只在应用层面上完成所谓的乱序重组以及超时重传等功能呢

而且这个是实打实可以用 wireshark/tshark 来抓包得到的效果(我之前调试过

EricPengShuai commented 1 year ago

@EricPengShuai

@Kiprey K 大,想确认一个问题,不管使用 TCPSocket 还是 CS144Socket 来实现传输,其底层是不是都走内核 tcp 的发送和接收?所以我们所做的工作是不是只在应用层面上完成所谓的乱序重组以及超时重传等功能呢

而且这个是实打实可以用 wireshark/tshark 来抓包得到的效果(我之前调试过

哦哦,这样啊,那 CS144Socket 就是在 tun/tab 机制上替换内核的 TCP/IP 协议传输数据么(那个 tun/tab 部分代码没看明白

bsg666 commented 1 year ago

@Kiprey

@bsg666

@Kiprey

@bsg666 博主,要实现与真实服务器通信,最后把TCPSocket换成CS144Socket的意思就是我们把内核协议栈换成了我们自己实现的协议栈了吗?这样理解对吗

严格意义上讲不对。无论是 TCPSocket 还是 CS144Socket ,它们都是用 tuntap 技术来直接把 TCP 报文(如果我没记错的话)直接注入进网络设备,而不走内核协议栈。

但 TCPSocket 是已经实现完备的代码,而 CS144Socket 是我们自己实现的代码。从 TCPSocket 换成 CS144Socket 其实就相当于控制变量,在原先 TCPSocket 能跑通并与真实世界交互成功的情况下,通过只更换所实现的 TCP 协议来达到测试 CS144Socket 功能的目的。

可是文章里知乎链接: tun/tap技术里面说的是tun设备里的数据还会发到用户程序里面,然后再通过socket发到内核协议栈,是我理解有问题吗?

那就是我记错了,感谢纠错!我复习了一下文章和代码,CS144 所实现的 TCPSocket 类实际上就是支持了 TCP 和 IP 协议这这两层。只不过 IP 协议这一层 CS144 已经通过 TCPOverIPv4OverTunFdAdapter 等类来模拟好了,因此我们只要模拟 TCP 层就好。

所以它还是会走内核协议栈,但是要怎么理解它用的是我们自己实现的协议栈呢?

Kiprey commented 1 year ago

@bsg666

所以它还是会走内核协议栈,但是要怎么理解它用的是我们自己实现的协议栈呢?

@EricPengShuai

哦哦,这样啊,那 CS144Socket 就是在 tun/tab 机制上替换内核的 TCP/IP 协议传输数据么(那个 tun/tab 部分代码没看明白

完整的理解是这样:

正常情况下(即不考虑CS144这门课,我们平时写代码时涉及到网络交互操作时)我们通过 glibc 内置的 socket 函数来在原始的内核协议栈上创建了一个 socket,然后后续我们所有往这个 socket 里写入的数据都是 应用层数据。内核协议栈会自己依次把这些应用层数据向下用 TCP 协议包裹起来,然后喂给 IP 层协议再被包裹成 IP 报文,然后依次往下。

但现在,在这门 CS144 课程中,我们要实现的是 运输层协议。也就是说 应用层数据(webget.cc #23) 需要透过我们所实现的 TCP 协议传递下去,因此我们肯定是不能去改应用层这层的数据的,不然远程服务器肯定识别不出来 HTTP 格式数据。那为了替换内核栈里已经实现好的 TCP 协议,改用我们自己实现的 TCP 协议,那就需要使用到 TUN/TAP 技术。

TUN 是一个虚拟网络设备,它模拟的是一个三层设备,通过它可以处理来自网络层的数据包,也就是 IP 数据包,换句话说 TUN 这个虚拟网络设备模拟的是一个 IP 协议层次的一个设备,所有直接发送到这个设备里的数据都必须是 IP 报文,而非原始的应用层数据。 那既然如此,我们需要实现一个中间件,这个中间件要做的事情大体上有几件事:

  1. 接受用户的应用层数据webget.cc #23,然后内部维护一个 TCP 状态,进而根据状态(例如超时、丢包等等)来生成出要发送的 TCP 包。
  2. 将中间件中刚生成出来的 TCP 包包一层 IP 头,转换为 IP 报文。
  3. 将生成的 IP 报文直接发送到 TUN 设备里。

这样一来,原先数据流向是 应用层数据 -> 内核 TCP 协议 -> 内核 IP 协议 -> 内核链路层协议 -> ....

现在变成了 应用层数据 -> 实现在用户层的 CS144 TCP 协议 -> 实现在用户层的 CS144 IP 协议 -> TUN 设备注入内核栈 -> 内核链路层协议 -> ...

这门课 CS144 就是实现 TCP 协议的,至于后面加粗的两个 CS144 IP 协议TUN 设备注入内核栈 这俩不需要我们操心,它已经实现在了代码里,并且自己会调用。

而这个大的中间件就是 CS144Socket。

EricPengShuai commented 1 year ago

@Kiprey 谢谢K大,现在明白了,很清晰👍

bsg666 commented 1 year ago

@Kiprey

@bsg666

所以它还是会走内核协议栈,但是要怎么理解它用的是我们自己实现的协议栈呢?

@EricPengShuai

哦哦,这样啊,那 CS144Socket 就是在 tun/tab 机制上替换内核的 TCP/IP 协议传输数据么(那个 tun/tab 部分代码没看明白

完整的理解是这样:

正常情况下(即不考虑CS144这门课,我们平时写代码时涉及到网络交互操作时)我们通过 glibc 内置的 socket 函数来在原始的内核协议栈上创建了一个 socket,然后后续我们所有往这个 socket 里写入的数据都是 应用层数据。内核协议栈会自己依次把这些应用层数据向下用 TCP 协议包裹起来,然后喂给 IP 层协议再被包裹成 IP 报文,然后依次往下。

但现在,在这门 CS144 课程中,我们要实现的是 运输层协议。也就是说 应用层数据(webget.cc #23) 需要透过我们所实现的 TCP 协议传递下去,因此我们肯定是不能去改应用层这层的数据的,不然远程服务器肯定识别不出来 HTTP 格式数据。那为了替换内核栈里已经实现好的 TCP 协议,改用我们自己实现的 TCP 协议,那就需要使用到 TUN/TAP 技术。

TUN 是一个虚拟网络设备,它模拟的是一个三层设备,通过它可以处理来自网络层的数据包,也就是 IP 数据包,换句话说 TUN 这个虚拟网络设备模拟的是一个 IP 协议层次的一个设备,所有直接发送到这个设备里的数据都必须是 IP 报文,而非原始的应用层数据。 那既然如此,我们需要实现一个中间件,这个中间件要做的事情大体上有几件事:

  1. 接受用户的应用层数据webget.cc #23,然后内部维护一个 TCP 状态,进而根据状态(例如超时、丢包等等)来生成出要发送的 TCP 包。
  2. 将中间件中刚生成出来的 TCP 包包一层 IP 头,转换为 IP 报文。
  3. 将生成的 IP 报文直接发送到 TUN 设备里。

这样一来,原先数据流向是 应用层数据 -> 内核 TCP 协议 -> 内核 IP 协议 -> 内核链路层协议 -> ....

现在变成了 应用层数据 -> 实现在用户层的 CS144 TCP 协议 -> 实现在用户层的 CS144 IP 协议 -> TUN 设备注入内核栈 -> 内核链路层协议 -> ...

这门课 CS144 就是实现 TCP 协议的,至于后面加粗的两个 CS144 IP 协议TUN 设备注入内核栈 这俩不需要我们操心,它已经实现在了代码里,并且自己会调用。

而这个大的中间件就是 CS144Socket。

解释的很清晰👍,谢谢K大!!

thewangcj commented 7 months ago

make check_lab4 执行的较为宽松的测试用例,即带 relaxed 版本的测试用例,类似 fsm_listen/fsm_ack_rst 是不检查的,所以不要像我一样单独执行这些用例,然后被折磨的怀疑人生😂

thewangcj commented 7 months ago

lab4 所有 tcp over ip 的测试用例都超时了,发现145没有收到144发来的包,抓144上的包发现一直在重发syn,且包直接就是 ip 头部开始,没有以太层的数据,不知道是不是 tun 的问题,试了下博主的代码也是同样的问题。

Kiprey commented 7 months ago

@thewangcj lab4 所有 tcp over ip 的测试用例都超时了,发现145没有收到144发来的包,抓144上的包发现一直在重发syn,且包直接就是 ip 头部开始,没有以太层的数据,不知道是不是 tun 的问题,试了下博主的代码也是同样的问题。

看这样子像是本机 tun/tap 没配置好的问题,不知道重新配一下能不能解决这个问题。

包是 IP 头主要是因为 TUN 设备接收的是 IP 包并将其注入内核栈。

albertethon commented 5 months ago

如果接收到的 TCP 数据包包含的 seqno 是无效的,则 TCPConnection 也需要回复一个类似的无效数据包。这是因为远程终端可能会发送无效数据包以确认当前连接是否有效,同时查看此时接收方的 ackno 和 window size。这被称为 TCP 的 keep-alive。

您好,看了下源码好像没有关于keep-alive的部分?源码中的need_send_ack只有在seq总数大于0时才为true?

另外,在用您的源码测试时发现lab4的Test152~Test160无法通过,请问是什么问题呀? image

image