TCP滑动窗口协议
TCP的首部中有一个很重要的字段就是16位长的窗口大小,它出现在每一个TCP数据报中,配合32位的确认序号,用于向对端通告本地socket的接收窗口大小。也就是说,如果本地socket发送一个TCP数据,其32位确认序号是5,窗口大小是5840,则用于告诉对端,对端已经发出的4个字节的数据已经收到并确认,接下来,本地socket最多能够接收从第5个字节开始的5840个字节长度的数据。这是由接收方进行的一种流量控制,接收方通过告诉发送方自己所能够接收数据的大小,达到控制发送方发送速度的目的。
结构体struct tcp_sock中有很多成员数据跟滑动窗口协议相关,需要注意的是这里讲的滑动窗口都是指本地socket的接收窗口。
成员window_clamp表示滑动窗口的最大值,滑动窗口的大小在变化的过程中不能超出这个值。它在TCP连接建立的时候被初始化,被置为最大的16位整数左移窗口的扩大因子,因为滑动窗口在TCP首部中以16位表示,window_clamp太大会导致滑动窗口不能在TCP首部中表示。
成员rx_opt是一个struct tcp_options_received结构体,它有两个成员snd_wscale和rcv_wscale,分别表示来自对端通告的滑动窗口扩大因子(本地发送数据报时需要遵守),和本地接收滑动窗口的扩大因子。snd_wscale从来自对端的第一个SYN中获取。rcv_wscale在本地socket建立连接时初始化,它赋值的原则是使16位整数的最大值左移rcv_wscale后,至少可以达到整个接收缓存的最大值。接收缓存最大值在协议栈中由全局变量mysysctl_rmem_max表示,它是256*(256+sizeof(struct sk_buff))后的值,为107520,但sysctl_tcp_rmem[3]所表示的接收缓存的上限更大,为174760,所以,取后者,这样的话,rcv_wscale的值几乎可以说是固定的,为2。所以window_clamp的值就是 65535 << 2 = 262140。可见,window_clamp的值超出了接收缓存的最大值,但这没有关系,因为在滑动窗口增长的时候,会考虑接收缓存的大小这个因素的。
rcv_wnd表示当前的接收窗口的大小,这个值在接收到来自对端的数据后,会变动的。它的初始值取接收缓存大小的3/4跟MAX_TCP_WINDOW之间的最小值,MAX_TCP_WINDOW在系统中的定义为32767U。然后,还要根据mss的值作一个调整,调整逻辑是:如果mss大于3*1460,则如果当前的rcv_wnd大于两倍的mss,就取两倍的mss作为rcv_wnd的值;如果mss大于1460,则如果当前的rcv_wnd大于3倍的mss,就取3倍的mss作为rcv_wnd的新值;否则,如果rcv_wnd大于4倍的mss,就取4倍的mss作为rcv_wnd的新值,我们的实验环境的mss值为1448(因为tcp首部有12字节的时间戳选项),所以rcv_wnd最后被调整为1448*4=5792。
rcv_ssthresh是当前的接收窗口大小的一个阀值,其初始值就置为rcv_wnd。它跟rcv_wnd配合工作,当本地socket收到数据报,并满足一定条件时,增长rcv_ssthresh的值,在下一次发送数据报组建TCP首部时,需要通告对端当前的接收窗口大小,这时需要更新rcv_wnd,此时rcv_wnd的取值不能超过rcv_ssthresh的值。两者配合,达到一个滑动窗口大小缓慢增长的效果。
rcv_wup记录滑动窗口的左边沿,即落在滑动窗口中的最小的一个序号。这样的话,rcv_wup+rcv_wnd即为滑动窗口的右边沿,rcv_wup+rcv_wnd-rcv_nxt即为滑动窗口的空白部分。它的初始值为0,在移动滑动窗口时被更新。 以上是关于接收滑动窗口的几个相关数据,下面我们看看它们是如何运用在TCP协议的通讯中的。
每次发送一个TCP数据报,都要构建TCP首部,这时,会调用my tcp_select_window选择窗口大小,窗口大小选择的基本思想是接收缓存剩余空间大小的3/4,但是不能超过rcv_ssthresh的大小。但是,如果这个新选择的窗口大小比当前窗口的剩余大小还小,则以当前窗口的剩余大小作为新窗口的大小。同时右移左边沿,令rcv_wup=rcv_nxt。这个新选择的窗口是受rcv_ssthresh限制的,一般不会有什么问题,但我们可以看到代码中还是作了一些上限判断,如果扩大因子为0,则窗口大小不能超过32767U,否则不能超过65535左移扩大因子后的值。
每次接收到来自对端的一个TCP数据报,且数据报长度大于128字节时,我们需要调用mytcp_grow_window,增加rcv_ssthresh的值,一般每次为rcv_ssthresh增长两倍的mss,增加的条件是rcv_ssthresh小于window_clamp,并且rcv_ssthresh小于接收缓存剩余空间的3/4,同时tcp_memory_pressure没有被置位(即接收缓存中的数据量没有太大)。tcp_grow_window中对新收到的skb的长度还有一些限制,并不总是增长rcv_ssthresh的值。具体见函数代码。
以上是关于接收窗口,下面简单看一下发送窗口。关于发送窗口,在struct tcp_sock中也有一些成员数据相关。
snd_wl1记录发送窗口更新时,造成窗口更新的那个ACK数据报的第一个序号。它主要用于在下一次判断是否需要更新发送窗口。
snd_wnd是发送窗口的大小,直接取值于来自对端的数据报的TCP首部。
max_window记录来自对端通告的窗口的最大值。
snd_una表示当前正等待ACK的第一个序号,而发送窗口实际上是在每次收到来自对端的ACK后,都会更新,所以,实际上snd_una成了发送窗口的左边沿。
TCP滑动窗口协议的更多相关文章
- UNIX网络编程——TCP 滑动窗口协议
什么是滑动窗口协议? 一图胜千言,看下面的图.简单解释下,发送和接受方都会维护一个数据帧的序列,这个序列被称作窗口.发送方的窗口大小由接受方确定,目的在于控制发送速度,以免接受方的缓存不够大, ...
- TCP之四:TCP 滑动窗口协议 详解
滑动窗口机制 滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口:同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口.发送窗口和接收窗口的序号的 ...
- TCP滑动窗口与回退N针协议
[转]TCP 滑动窗口协议/1比特滑动窗口协议/后退n协议/选择重传协议 2014-1-5阅读884 评论0 本文转自 http://www.cnblogs.com/ulihj/archive/201 ...
- TCP协议总结--停止等待协议,连续ARQ协议,滑动窗口协议
前言:在学习tcp三次握手的过程之中,由于一直无法解释tcpdump命令抓的包中seq和ack的含义,就将tcp协议往深入的了解了一下,了解到了几个协议,做一个小结. 先来看看我的问题: 这是用tcp ...
- TCP协议的滑动窗口协议以及流量控制
参考资料 http://blog.chinaunix.net/uid-26275986-id-4109679.html http://network.51cto.com/art/201501/4640 ...
- 面试之路(29)-TCP流量控制和拥塞控制-滑动窗口协议详解
拥塞: 拥塞发生的主要原因在于网络能够提供的资源不足以满足用户的需求,这些资源包括缓存空间.链路带宽容量和中间节点的处理能力.由于互联网的设计机制导致其缺乏"接纳控制"能力,因此在 ...
- 一篇带你读懂TCP之“滑动窗口”协议
前言 你现在的努力,是为了以后有更多的选择. 在上一篇文章通过"表白"方式,让我们快速了解网络七层协议了解了网络七层协议. 接下来我们要把重心放在网络传输的可靠性上面.一起来看TC ...
- 面试连环炮系列(二十):TCP的滑动窗口协议是什么
TCP的滑动窗口协议是什么 滑动窗口协议,用于网络数据传输时的流量控制,以避免拥塞的发生.该协议允许发送方在停止并等待确认前发送多个数据分组.由于发送方不必每发一个分组就停下来等待确认,因此该协议可以 ...
- TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释
一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...
随机推荐
- Splunk Web页面的登录密码忘记了怎么办
splunk的web登录密码忘记的话,可以使用以下方法重置. 一.关闭splunk服务 /opt/splunk/bin/splunk stop 二.删除默认密码配置文件 三.重启启动splunk服务, ...
- redis使用日志(4):如何让外部服务器访问
开启redis 允许外网IP 访问 在 Linux 中安装了redis 服务,当在客户端通过远程连接的方式连接时,报could not connect错误. 错误的原因很简单,就是没有连接上redis ...
- [DIOCP3-说明书] 关于DEMO的编译
总有些朋友问我,关于DEMO编译的一些问题,每次都回答大概都差不多,我想还是写篇说明书给大家,关于DEMO编译的步骤. [环境设定] 1.将DIOCP3\source路径添加到Delphi的搜索路 ...
- java 多线程 19: ReentrantLock 与 Condition
ReentrantLock ReentrantLock,一个可重入的互斥锁,它具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大. Reentran ...
- Logistic回归分析简介
Logistic回归:实际上属于判别分析,因拥有很差的判别效率而不常用. 1. 应用范围: ① 适用于流行病学资料的危险因素分析 ② 实验室中药物的剂量-反应关系 ③ 临床试验 ...
- 基于jQuery Tooltips悬停提示效果
基于jQuery Tooltips悬停提示效果.这是一款基于jquery.tooltipster插件实现的jQuery Tooltips Hover effect特效.效果图如下: 在线预览 源码 ...
- python 6种数据类型几及用法
#!/usr/bin/python3 #python的基本语法和数据类型 #python3中 一行有多个语句,用分号分割(;) print("aaa") ;print(" ...
- [转]ORA-01555错误总结(二)
原文地址:http://blog.csdn.net/oradh/article/details/25683769 这篇文章紧接着上一篇“ORA-01555错误总结(一)”,主要描述延迟块清除导致的OR ...
- spark streaming从指定offset处消费Kafka数据
spark streaming从指定offset处消费Kafka数据 -- : 770人阅读 评论() 收藏 举报 分类: spark() 原文地址:http://blog.csdn.net/high ...
- 【Unity】角色受伤后的闪烁(blink/flash)效果
玩家受伤后,一段时间内快速闪烁.这里想要的闪烁效果是玩家快速的显隐切换效果,而不是玩家变白的情况. 快速切换玩家的显隐效果不能用SetActive修改角色物体本身的激活状态,因为玩家角色身上的其他脚本 ...