在上一文中我们已经介绍了滑动窗口的基本概念,以及它的目的。本文我们就亲自动手实践一下。
1. 环境准备
git 地址:https://git.oschina.net/ivan_allen/unp.git
- 服务器:
unp/protocol/tools/tcpserver/sink_serv.c
,部署在 Linux 上。 - 客户端:
/home/allen/unp/protocol/tools/winclient/sink_client.cpp
,部署在 Windows 上。
服务器之所以叫 sink_serv,是因为它就是个黑洞,它接收到数据后就直接扔了,即石沉大海了(实际上,代码中将接收到的数据打印在屏幕上了)。服务器每隔 500 毫秒从接收缓冲区读一次数据,一次最多读 1024 字节。
客户端每次向服务器发送 1024 字节的数据,本质上是向自己的发送缓冲区写入 1024 字节数据。连续发送 count 次,count 可以通过命令行参数指定。
2. 实验
- 启动服务器
图1 服务器启动
从图 1 中我们看到服务器最后一个启动参数是 4096,它表示将接收缓冲区大小设置为 4096. 然而,内核在设置缓冲区大小的时候,会把缓冲区大小设置为这个值的 2 倍(具体原因请参考 man 手册),因此可以看到第 4 行打印 actual recvbufsize:8192.
- 在 windows 上打开 OmniPeek 准备抓包,同时启动客户端
sink_client.exe 192.168.80.129 8000 8
参数 8 表示客户端连续发送 8 次数据,每次 1024 字节。
3. 抓包结果
图2 OmniPeek 抓包结果
图3 时序图
在时序图中,ACK n 表示对序号为 n 的 TCP 段进行确认。
图4 滑动窗口分析
图 4 中,我们用绿色表示发送方,蓝色表示接收方加送的信号。在一开始的时候,接收方通告了一个大小为 2920 大小的窗口,接下来发送方发送了 4 号报文,大小为 1024 B,然后接收方确认了 4 号报文,并通告了一个大小为 2920 大小的窗口。后面依此类推。
4. 总结
- 掌握滑动窗口的工作原理
最后再次强调一下,学习滑动窗口,我们假设网络是理想的,不拥塞,只要发了数据,对方一定能收到。