分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow
写前一篇文章TCP的乱序和丢包判断(附Reordering更新算法)-理论的时候,我觉得我在一边拉一边吃,玩的都是排泄物,言之无味,不知所云,我想把一些能看得见摸得着的东西独立出来,就成了本文,如果有一天我忘掉了TCP的细节,我想我直接把本文的例子跑一遍,应该就能拾起个大概了。
声明
本文完全旨在解释上一篇文章里那些枯燥的理论,我实在是觉得自己文字功底差,一直以来都倾向于用例子来给出解释。花了点时间整理了几个用例,希望能把问题解释清楚。在用实例解释问题的时候,最忌讳的是把很多因素杂糅了一起,因为本来就是通过特例解释,并没有完备性支撑,所以我尽量把问题孤立化,加之以前也写了不少文章解释其它的方面,所以本文的所有用例均采用以下的配置:
net.ipv4.tcp_fack = 0net.ipv4.tcp_sack = 1net.ipv4.tcp_congestion_control = cubic
- 1
- 2
- 3
关于fack开启的情形,请自行分析。另外本文的主要目的是解释reordering相关的,不是拥塞算法,所以默认采用了cubic算法,至于其它的比如bbr算法(以及任何携带cong_control回调的拥塞控制算法)下是什么表现,本文不涉及。
另外,本文的所有实例均是packetdrill脚本,如果你不会的话就请自行谷歌百度packetdrill的使用方法并下载安装,本文并不负责介绍关于packetdrill的任何东西,给出一个链接算是比较厚道了:Packetdrill 简明使用手册。
case 1:认识乱序空洞左边缘确定
这个用例可以让你清晰看懂如何来确定乱序空洞的边缘在哪里以及如何确定。为此我准备了两个packetdrill脚本来进行对比性解释。首先看第一个,packetdrill代码如下:
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0+0 setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0+0 bind(3, ..., ...) = 0+0 listen(3, 1) = 0+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>+0 > S. 0:0(0) ack 1 <...>+.1 < . 1:1(0) ack 1 win 32792+0 accept(3, ..., ...) = 4+0 write(4, ..., 1000) = 1000// 确保已经确认到了1001+.1 < . 1:1(0) ack 1001 win 32792// 连续发送10个段+0 write(4, ..., 10000) = 10000+.0 %{ print tcpi_reordering }%// 重复确认1001,同时携带一个6001-7001的SACK+.1 < . 1:1(0) ack 1001 win 257 <sack 6001:7001,nop,nop>// 随即重复确认1001,同时再携带两个SACK+.0 < . 1:1(0) ack 1001 win 257 <sack 2001:3001 9001:10001,nop,nop>+.0 %{ print tcpi_reordering }%// 最终完全确认10个数据包+5 < . 1:1(0) ack 10001 win 257+.0 %{ print tcpi_reordering }%
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
以下是脚本的输出:
3 8 8
- 1
- 2
- 3
下面我给出一个解析,解释发生了什么。我把整个事情发生的过程整理成下图:
可见,虽然输出的是3,8,8,但事实上,由于reordering值的更新是单调递增的,所以reordering值经过的第二次8到7的更新是失败的,真实的reordering更新尝试应该是3,8,7.
最终我们来看一下以上脚本过程的抓包:
第一个脚本到此结束了。
接下来我们看下case 1的第二个例子,该例子说明了乱序空洞的右边缘如何确定。首先还是先给出packetdrill脚本的代码:
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +0 setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0 +0 bind(3, ..., ...) = 0 +0 listen(3, 1) = 0 +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7> +0 > S. 0:0(0) ack 1 <...> +.1 < . 1:1(0) ack 1 win 32792 +0 accept(3, ..., ...) = 4 +0 write(4, ..., 1000) = 1000 +.1 < . 1:1(0) ack 1001 win 32792 +0 write(4, ..., 10000) = 10000 +.0 %{ print tcpi_reordering }%+