TCP协议当中最重要的部分就是流量控制(flow control)和拥塞控制(congestion control)了。
TCP协议的流量控制是通过窗口机制实现的,:-)。只听这些概念很抽象,扭头就忘了,我们用个实例来看看。
使用的工具是 tcpdump。使用这个工具获取一下访问本机的web服务器所产生的数据如下:
22:14:27.757059 IP ubuntu-xingwang.39585 > ubuntu-xingwang.http: Flags [S], seq 779326623, win 43690, options [mss 65495,sackOK,TS val 1423721 ecr 0,nop,wscale 7], length 0
22:14:27.757093 IP ubuntu-xingwang.http > ubuntu-xingwang.39585: Flags [S.], seq 283855395, ack 779326624, win 43690, options [mss 65495,sackOK,TS val 1423721 ecr 1423721,nop,wscale 7], length 0
22:14:27.757121 IP ubuntu-xingwang.39585 > ubuntu-xingwang.http: Flags [.], ack 1, win342, options [nop,nop,TS val 1423721 ecr 1423721], length 0
22:14:27.757375 IP ubuntu-xingwang.39585 > ubuntu-xingwang.http: Flags [P.], seq 1:372, ack 1, win 342, options [nop,nop,TS val 1423721 ecr 1423721], length371
22:14:27.757421 IP ubuntu-xingwang.http > ubuntu-xingwang.39585: Flags [.], ack 372, win 350, options [nop,nop,TS val 1423721 ecr 1423721], length 0
22:14:27.759204 IP ubuntu-xingwang.http > ubuntu-xingwang.39585: Flags [P.], seq 1:380, ack 372, win 350, options [nop,nop,TS val 1423722 ecr 1423721], length 379
22:14:27.759236 IP ubuntu-xingwang.39585 > ubuntu-xingwang.http: Flags [.], ack 380, win 350, options [nop,nop,TS val 1423722 ecr 1423722], length 0
22:14:32.667501 IP ubuntu-xingwang.http > ubuntu-xingwang.39585: Flags [F.], seq 380, ack 372, win 350, options [nop,nop,TS val 1424949 ecr 1423722], length 0
22:14:32.667748 IP ubuntu-xingwang.39585 > ubuntu-xingwang.http: Flags [F.], seq 372, ack 381, win 350, options [nop,nop,TS val 1424949 ecr 1424949], length 0
22:14:32.667801 IP ubuntu-xingwang.http > ubuntu-xingwang.39585: Flags [.], ack 373, win 350, options [nop,nop,TS val 1424949 ecr 1424949], length 0
可以说是教科书般的流量啊,三次握手建立链接(蓝色流量)和四次握手断开链接(红色流量)一清二楚。
我们要注意的就是每条数据中的 win 字段数据,这就是传说中的窗口(window)了。这个值就是告诉链接中的另一方,我端的缓存空间现在是这么大,下次发送数据的时候别发太多,要不就会有数据无法保存下来,发生丢失。这就是TCP的流量控制方法。
我们来看具体的数据,第三条数据中,本地端口告知服务器,本地的缓存空间暂时只有 342 字节了。按说服务器再次发送数据的时候不会超过这个数的。可是实际上,第四条服务器发送了长度为372字节的数据。这是为什么呢?
原来TCP协议刚制定的时候,只给win字段分配了两个字节的空间,那么他的最大数就是65536字节,64K。但是为了更高效地使用带宽很高的网络,科学家们就增加了一个 窗口扩大因子(window scale factor)选项来增加窗口的值。在第一次syn发出的时候,客户端的选项数据里的wscale字段值设置为了7。就是说今后这个端所有的窗口数据都要左移7位,也就是342乘以128,那就是43776字节了。所以服务器发送了372个字节,太小意思了,远远没有超过本地缓存能力呢,呵呵
窗口扩大因子可以是0-14中间的任意一个值。