在tcp_ack接收ACK处理函数中,如果确认当前走慢速路径,那么会调用tcp_ack_update_window函数检查窗口是否需要更新并更新之,并且更新未确认数据的位置,即更新窗口左边沿;

 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
/* 快速路径&& ack确认了新数据 */
if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
;
}
/* 慢速路径 */
else {
/* 更新发送窗口 */
flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
}
}

tcp_ack_update_window执行窗口更新主流程,函数首先根据窗口扩大因子计算实际的窗口大小,然后判断是否需要更新窗口,若需要则对窗口进行更新,注意,只有当窗口不相等的情况下才会实际更新窗口,否则只更新最后一次窗口更新ack序号;窗口更新需要更新窗口,同步MSS,检查是否开启快速路径等;函数最后还将设置未确认数据位置,即窗口左边沿;

 /* Update our send window.
*
* Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
* and in FreeBSD. NetBSD's one is even worse.) is wrong.
*/
static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 ack,
u32 ack_seq)
{
struct tcp_sock *tp = tcp_sk(sk);
int flag = ;
u32 nwin = ntohs(tcp_hdr(skb)->window); /* 根据扩大因子计算窗口大小 */
if (likely(!tcp_hdr(skb)->syn))
nwin <<= tp->rx_opt.snd_wscale; /* 需要更新窗口的话 */
if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
/* 窗口更新标记 */
flag |= FLAG_WIN_UPDATE; /* 记录窗口更新的ack序号 */
tcp_update_wl(tp, ack_seq); /* 发送窗口与通告窗口不等时 */
if (tp->snd_wnd != nwin) { /* 更新发送窗口*/
tp->snd_wnd = nwin; /* Note, it is the only place, where
* fast path is recovered for sending TCP.
*/
/* 判断是否开启快路标志 */
tp->pred_flags = ;
tcp_fast_path_check(sk); /* 有数据要发送 */
if (tcp_send_head(sk))
tcp_slow_start_after_idle_check(sk); /* 窗口大于以前记录的最大窗口 */
if (nwin > tp->max_window) {
/* 更新最大窗口 */
tp->max_window = nwin;
/* 更新mss */
tcp_sync_mss(sk, inet_csk(sk)->icsk_pmtu_cookie);
}
}
} /* 更新未确认的数据位置,即窗口左边沿 */
tcp_snd_una_update(tp, ack); return flag;
}

tcp_may_update_window用于判断窗口是否需要更新,满足以下条件之一则更新:

(1) ACK确认了新的数据;

(2) 未满足(1),ACK未确认数据,通过上面snd_una<=ack的条件,此时只能是snd_una=ack,即未确认新数据,是个重复ack,但是这个ack的序号比之前更新窗口的序号要新,则需要更新snd_wl1;

(3) 未满足(1)(2),未确认数据,ack需要也未更新,但是窗口有所改变,则说明单单发送了一个窗口更新通知;

 /* Check that window update is acceptable.
* The function assumes that snd_una<=ack<=snd_next.
*/
static inline bool tcp_may_update_window(const struct tcp_sock *tp,
const u32 ack, const u32 ack_seq,
const u32 nwin)
{
/*
更新条件
ack确认序号确认了数据,意味着窗口要收缩
ack确认序号未确认新数据,ack序号比上一个更新窗口ack序号要新
ack序号与上一个更新装ack序号一致,但是窗口比以前的窗口大
*/
return after(ack, tp->snd_una) ||
after(ack_seq, tp->snd_wl1) ||
(ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd);
}

TCP发送窗口更新tcp_ack_update_window的更多相关文章

  1. TCP滑动窗口协议

    TCP的首部中​有一个很重要的字段就是16位长的窗口大小,它出现在每一个TCP数据报中,配合32位的确认序号,用于向对端通告本地socket的接收窗口大小.也就是说,如果本地socket发送一个TCP ...

  2. 彻底搞通TCP滑动窗口

    在我们当初学习网络编程的时候,都接触过TCP,在TCP中,对于数据传输有各种策略,比如滑动窗口.拥塞窗口机制,又比如慢启动.快速恢复.拥塞避免等.通过本文,我们将了解滑动窗口在TCP中是如何使用的. ...

  3. TCP滑动窗口(发送窗口和接受窗口)

    TCP窗口机制 TCP header中有一个Window Size字段,它其实是指接收端的窗口,即接收窗口.用来告知发送端自己所能接收的数据量,从而达到一部分流控的目的. 其实TCP在整个发送过程中, ...

  4. TCP 滑动窗口和 拥塞窗口

    转http://coolshell.cn/articles/11609.html 滑动窗口 -- 表征发送端和接收端的接收能力 拥塞窗口-- 表征中间设备的传输能力 TCP滑动窗口 需要说明一下,如果 ...

  5. TCP 滑动窗口

    滑动窗口协议 流量控制方法 PUSH 慢启动   隔一个报文段确认"的策略实际就是因为 delayed ack,同时接收到两个待确认的ACK包时,就立即发送确认包.   滑动窗口实例   解 ...

  6. TCP发送源码学习(2)--tcp_write_xmit

    一.tcp_write_xmit()将发送队列上的SBK发送出去,返回值为0表示发送成功.函数执行过程如下:1.检测拥塞窗口的大小.2.检测当前报文是否完全处在发送窗口内.3.检测报文是否使用nagl ...

  7. TCP发送源码学习(1)--tcp_sendmsg

    一.tcp_sendmsg()函数分析: int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t ...

  8. TCP 接收窗口自动调节

    https://technet.microsoft.com/zh-cn/magazine/2007.01.cableguy.aspx 欢迎来到 TechNet 杂志“网络专家”的第一部分.TechNe ...

  9. TCP 三次握手四次挥手, ack 报文的大小.tcp和udp的不同之处、tcp如何保证可靠的、tcp滑动窗口解释

    一.TCP三次握手和四次挥手,ACK报文的大小 首先连接需要三次握手,释放连接需要四次挥手 然后看一下连接的具体请求: [注意]中断连接端可以是Client端,也可以是Server端. [注意] 在T ...

随机推荐

  1. 【漏洞分析】Discuz! X系列全版本后台SQL注入漏洞

    0x01漏洞描述 Discuz!X全版本存在SQL注入漏洞.漏洞产生的原因是source\admincp\admincp_setting.php在处理$settingnew['uc']['appid' ...

  2. Windows地址栏的妙用

    主角: 它就是windows自带的一个小工具->地址栏,可以通过在任务栏右键选择工具栏-地址栏添加使用. 妙用: 一.打开文件 使用方法:D:\Temp(文件路径) 小提示:快速进入回收站:Re ...

  3. php的协程

    有关迭代生成器的内容在这篇博客中 协程 协程的支持是在迭代生成器的基础上, 增加了可以回送数据给生成器的功能(调用者发送数据给被调用的生成器函数). 这就把生成器到调用者的单向通信转变为两者之间的双向 ...

  4. mysql调优——数据包大小限制max_allowed_packet

     mysql根据配置文件会限制server接受的数据包大小. 有时候大的插入和更新会受max_allowed_packet 参数限制,导致写入或者更新失败. 查看目前配置 show VARIABLES ...

  5. Spring基础01——在IDEA中编写spring.xml

    如果需要在IDEA自动创建spring.xml配置文件,那么我们就需要先引入Spring相关的依赖 <dependency> <groupId>org.springframew ...

  6. C++——INI文件详解

    原创声明:本文系博主原创文章,转载及引用请注明出处. 1. INI文件介绍 INI是英文单词 INItialization 的缩写,常作为Windows系统下的配置文件.INI文件是文本文件,通常用于 ...

  7. 转 shell中的多进程【并发】

    原文地址https://bbs.51cto.com/thread-1104907-1-1.html 根据我个人的理解, 所谓的多进程 只不过是将多个任务放到后台执行而已,很多人都用到过,所以现在讲的主 ...

  8. ssh客户端命令

  9. mac 环境下Android 反编译源码

    mac环境下Android 反编译 一.需要的工具 apktool:反编译APK文件,得到classes.dex文件,同时也能获取到资源文件以及布局文件. dex2jar:将反编译后的classes. ...

  10. Java 解析自定义XML文件

    这里我用 maven项目 作为 演示 配置pom.xml文件 完整的pom.xml文件信息 <?xml version="1.0" encoding="UTF-8& ...