tcpack--3快速确认模式- ack状态发送&清除
ACK发送状态的转换图

ACK的发送状态清除
当成功发送ACK时,会删除延迟确认定时器,同时清零ACK的发送状态标志icsk->icsk_ack.pending
ACK发送事件主要做了:更新快速确认模式中的ACK额度,删除ACK延迟定时器,清零icsk->icsk_ack.pending。
在快速确认模式中,可以发送的ACK数量是有限制的,具体额度为icsk->icsk_ack.quick。当额度用完时,就进入延迟确认模式。
static int tcp_transmit_skb (struct sock *sk, struct sk_buff *skb, int clone_it, gfp_t gfp_mask)
{
------------------------------
if (likely(tcb->tcp_flags & TCPHDR_ACK))
tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); /* ACK发送事件的处理 */
------------------------------------------------
}
//ACK发送事件主要做了:更新快速确认模式中的ACK额度,删除ACK延迟定时器,清零icsk->icsk_ack.pending。
/* Account for an ACK we sent. */
static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
tcp_dec_quickack_mode(sk, pkts);// 更新快速确认模式的ACK额度
inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);//删除ACK延迟定时器
}
static inline void tcp_dec_quickack_mode (struct sock *sk, const unsigned int pkts)
{
struct inet_connection_sock *icsk = inet_csk(sk); if (icsk->icsk_ack.quick) { /* 如果额度不为0 */
if (pkts >= icsk->icsk_ack.quick) {
icsk->icsk_ack.quick = 0;
/* Leaving quickack mode we deflate ATO. */
icsk->icsk_ack.ato = TCP_ATO_MIN;
} else
icsk->icsk_ack.quick -= pkts;
}
快速确认:
- tcp_enter_quickack_mode: 进入快速确认模式,设置快速确认模式标志,设置在快速确认模式中可以发送的ACK数量
/*
在快速确认模式中,可以发送的ACK数量是有限制的,具体额度为icsk->icsk_ack.quick。
所以进入快速确认模式时,需要设置可以快速发送的ACK数量,一般允许快速确认半个接收窗口的数据量,但最多不能超过16个,最少为2个。
*/
static void tcp_enter_quickack_mode (struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk); tcp_incr_quickack(sk); /* 设置在快速确认模式中可以发送的ACK数量 */
icsk->icsk_ack.pingpong = 0; /* 快速确认模式的标志 */
icsk->icsk_ack.ato = TCP_ATO_MIN; /* ACK超时时间 */ }
static void tcp_incr_quickack(struct sock *sk)
{/* Maximal number of ACKs sent quickly to accelerate slow-start. */
#define TCP_MAX_QUICKACKS 16U
struct inet_connection_sock *icsk = inet_csk(sk);
unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss); if (quickacks == 0)
quickacks = 2;
if (quickacks > icsk->icsk_ack.quick)
icsk->icsk_ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
}
- tcp_in_quickack_mode:检查是否处于快速确认模式。如果设置了快速确认标志,且快速确认模式中可以发送的ACK数量不为0,就判断连接处于快速确认模式中
/* Send ACKs quickly, if "quick" count is not exhausted
* and the session is not interactive.
*/ static bool tcp_in_quickack_mode(struct sock *sk)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
const struct dst_entry *dst = __sk_dst_get(sk);
//如果快速确认模式中可以发送的ACK数量不为0,且设置了快速确认标志 且 dst 路由存在
return (dst && dst_metric(dst, RTAX_QUICKACK)) ||
(icsk->icsk_ack.quick && !icsk->icsk_ack.pingpong);
}
- 在 tcp_rcv_state_process 以及tcp_rcv_established中 处理完接收到的报文处理完之后;会调用_tcp_ack_snd_check()来发送快速确认或延迟确认
tcp_ack_snd_check()会检查是否需要发送ACK,以及是使用快速确认还是延迟确认。
/*
static inline int inet_csk_ack_scheduled(const struct sock *sk)
{
return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
} */
static inline void tcp_ack_snd_check(struct sock *sk)
{
if (!inet_csk_ack_scheduled(sk)) {//如果没有ACK需要发送
/* We sent a data segment already. */
return;
}
__tcp_ack_snd_check(sk, 1);
}
对于以下情况可以立即发送ACK,即进行快速确认:
1. 接收缓冲区中有一个以上的全尺寸数据段仍然是NOT ACKed,并且接收窗口变大了。所以一般收到了两个数据包后,会发送ACK,而不是对每个数据包都进行确认。
2. 此时处于快速确认模式中。
3. 乱序队列不为空。
/*
* Check if sending an ack is needed.
*/
static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
{
struct tcp_sock *tp = tcp_sk(sk); /* More than one full frame received... */
if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss &&
/* ... and right edge of window advances far enough.
* (tcp_recvmsg() will send ACK otherwise). Or...
*/
__tcp_select_window(sk) >= tp->rcv_wnd) ||
/* We ACK each frame or... */
tcp_in_quickack_mode(sk) ||
/* We have out of order data. */
(ofo_possible && !RB_EMPTY_ROOT(&tp->out_of_order_queue))) {
/* Then ack it now ACK的发送函数为tcp_send_ack(),如果发送失败会启动ACK延迟定时器。 */
tcp_send_ack(sk);
} else {
/* Else, send delayed ack. */
tcp_send_delayed_ack(sk);
}
}
TCP_QUICKACK选项
TCP_QUICKACK用于让本端立即发送ACK,而不进行延迟确认。需要注意的是,这个选项并不是可持续的,之后还是有可能进入延迟确认模式的。
所以如果需要一直进行快速确认,要在每次调用接收函数后都进行选项设置。
tcpack--3快速确认模式- ack状态发送&清除的更多相关文章
- tcpack--3快速确认模式
接收到数据报后,会调用tcp_event_data_recv(),不管是在慢速路径的tcp_data_queue中调用还是 在快速路径中处理接收数据后直接调用,注意(如果len <= tcp_h ...
- TCP的ACK确认系列 — 快速确认
主要内容:TCP的快速确认.TCP_QUICKACK选项的实现. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 快速确认模式 (1) 进入快速确认模式 ...
- 消息中间件系列三:使用RabbitMq原生Java客户端进行消息通信(消费者(接收方)自动确认模式、消费者(接收方)自行确认模式、生产者(发送方)确认模式)
准备工作: 1)安装RabbitMQ,参考文章:消息中间件系列二:RabbitMQ入门(基本概念.RabbitMQ的安装和运行) 2.)分别新建名为OriginalRabbitMQProducer和O ...
- SpringCloud(六) - RabbitMQ安装,三种消息发送模式,消息发送确认,消息消费确认(自动,手动)
1.安装erlang语言环境 1.1 创建 erlang安装目录 mkdir erlang 1.2 上传解压压缩包 上传到: /root/ 解压缩# tar -zxvf otp_src_22.0.ta ...
- 可靠通信的保障 —— 使用ACK机制发送自定义信息——ESFramework 通信框架4.0 快速上手(12)
使用ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter接口的Send方法,我们已经可以给服务端或其它在线客户端发送自定义信息了, ...
- RabbitMQ:消息发送确认 与 消息接收确认(ACK)
默认情况下如果一个 Message 被消费者所正确接收则会被从 Queue 中移除 如果一个 Queue 没被任何消费者订阅,那么这个 Queue 中的消息会被 Cache(缓存),当有消费者订阅时则 ...
- rabbitmq 持久化 事务 发送确认模式
部分内容来自:http://blog.csdn.net/hzw19920329/article/details/54315940 http://blog.csdn.net/hzw19920329/ar ...
- Linux下TCP延迟确认(Delayed Ack)机制导致的时延问题分析
版权声明:本文由潘安群原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/105 来源:腾云阁 https://www.qclo ...
- TCP:WireShark分析,序列号Seq和确认号Ack
转载自 http://blog.csdn.net/a19881029/article/details/38091243 序列号为当前端成功发送的数据位数,确认号为当前端成功接收的数据位数,SYN标志位 ...
随机推荐
- 多测试_常用linux命令_002
linux 介绍 常用的操作系统(os): windows .dos.android.ios.unix.linux linux系统:是一个免费.开源的操作系统 支持多cpu,多用户,多线程的操作系统, ...
- MeteoInfoLab脚本示例:添加南海脚图
添加南海脚图实际上就是增加一个地图坐标系(Axesm),在用axesm函数创建地图坐标系的时候可以指定position参数(即位置和大小),第1和第2个参数是坐标系的左下角x, y位置,后两个参数是坐 ...
- 基于python实现顺序存储的队列代码
""" 队列-顺序存储 seqqueue.py 代码实现 """ # 自定义异常类 class QueueError(Exception): ...
- python 微信小程序自动化
微信小程序自动化 https://www.cnblogs.com/yyoba/python27 - FautoTesthttps://www.cnblogs.com/yyoba/p/9973731.h ...
- django—ORM相关
常用的QuerySet方法 1.all() 查询表中所有数据,返回一个QuerySet对象列表 2.filter() 查询满足条件的数据,返回一个QuerySet对象列表 3.get() 查询指定的数 ...
- LC滤波器简单设计法 - 一文读懂LC滤波器简单设计方法及原理介绍,LC值计算方法
LC滤波器概述 LC滤波器也称为无源滤波器,是传统的谐波补偿装置.LC滤波器之所以称为无源滤波器,顾名思义,就是该装置不需要额外提供电源.LC滤波器一般是由滤波电容器.电抗器和电阻器适当组合而成,与谐 ...
- 02 . Go框架之Gin框架从入门到熟悉(数据解析和绑定,渲染,重定向,同步异步,中间件)
数据解析和绑定 json数据解析和绑定 package main import ( "github.com/gin-gonic/gin" "net/http" ...
- pip intsall 遇到的各种问题
一.pip install 安装指定版本的包 要用pip 安装指定版本的python的包,只需要通过 == 操作符指定. pip install robotframework == 2.8.7 将安装 ...
- NB-IOT关键技术分析
NB-IOT(NarrowBand Internet of Things,窄带IoT)是一种基于蜂窝的窄带物联网技术,支持低功耗设备在广域网的蜂窝数据连接.NB-IOT在物联网应用广泛,许多领域都充分 ...
- ElasticSearch初步了解和安装(windows上安装)
ElasticSearch是什么 ElasticSearch(一般简称es)是一个基于Lucene的分布式搜索和数据分析引擎.它提供了REST api 的操作接口.它可以快速的存储.搜索.分析海量数据 ...