tcp报文什么时候会真正发送

当用户使用tcp socket发送数据时,数据会立即被发送吗?不一定,tcp报文真正的发送由内核来定。那么满足什么条件的时候,tcp报文才会真正被发送?

用户调用tcp socket的send函数,在内核调用tcp_sendmsg进入tcp协议栈,tcp协议栈的出口是tcp_transmit_skb,通过该函数将报文发送给ip层。

讨论tcp报文什么时候会真正发送,先看一下有哪些条件会导致tcp报文不会被发送,当这些条件都不满足的时候,那么tcp就会被真正发送。本文只列出一个典型的环节,tcp协议栈的具体实现要复杂的多。

autocroking

自动软木塞,在满足某些条件时,数据不会被立即发送,而是在缓冲区缓存。

/* If a not yet filled skb is pushed, do not send it if

* we have data packets in Qdisc or NIC queues :

* Because TX completion will happen shortly, it gives a chance

* to coalesce future sendmsg() payload into this skb, without

* need for a timer, and with no latency trade off.

* As packets containing data payload have a bigger truesize

* than pure acks (dataless) packets, the last checks prevent

* autocorking if we only have an ACK in Qdisc/NIC queues,

* or if TX completion was delayed after we processed ACK packet.

*/

static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,

int size_goal)

{

return skb->len < size_goal &&

READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_autocorking) &&

!tcp_rtx_queue_empty(sk) &&

refcount_read(&sk->sk_wmem_alloc) > skb->truesize &&

tcp_skb_can_collapse_to(skb);

}

这个条件判断的比较谨慎,只有4个条件都满足时,才不会立即发送。

(1)数据的长度小于size goal,还没有达到目标,先不发送。size goal是基于mss和gso计算出来的,一般比mss要大。

(2)autocorking使能,我感觉这个条件应该作为第一个条件,这个功能的开关。

(3)sk->sk_wmem_alloc每向下层队列发送,则会增加;发送完成,则会减少。该条件满足,说明在底层队列中还有数据没有发送。

(4)当前这个skb还有一些空间没有使用,还可以追加一些数据,这个时候,可以不发送

tsq tasklet

被autocorkong限流的报文什么时候会真正发送?通过tsq tasklet发送,如下代码所示,当对socket进行限流时,会设置一个标记TSQ_THROTTLED。

if (tcp_should_autocork(sk, skb, size_goal)) {

/* avoid atomic op if TSQ_THROTTLED bit is already set */

if (!test_bit(TSQ_THROTTLED, &sk->sk_tsq_flags)) {

NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);

set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);

}

/* It is possible TX completion already happened

* before we set TSQ_THROTTLED.

*/

if (refcount_read(&sk->sk_wmem_alloc) > skb->truesize)

return;

}

当报文从底层队列中发走并释放skb时,会调用函数tcp_wfree,在该函数中会调度tsq_tasklet,最后发送socket中的数据。

tsq全称为tcp small queue,避免在底层队列中有太多的小包,在autocorking中做的事情和在函数tcp_small_queue_check中做的事情是相似的。

tasklet是小任务,linux中任务延后执行的机制有软中断、tasklet。延后执行的机制,在应用开发中也常用到,比如线程池,可以延后处理任务。

拥塞窗口和发送窗口

拥塞窗口主要看已经发送还没有确认的报文数量,如果这些报文的数量大于拥塞窗口,则不发送。

发送窗口看要发送的数据是不是超过了发送窗口的大小,如果是,则不发送。

发送窗口由接收侧控制,在tcp建立连接的过程中会根据初始条件确定发送窗口的大小,

拥塞窗口:慢启动,拥塞避免,拥塞处理

发送窗口:由接收窗口决定

nagle

收到ack的时候

重传

定时机制

用户控制

相关推荐
墨风如雪5 小时前
甲骨文云(Oracle Cloud)最新注册防坑记录:被ABC了怎么办?
服务器
道清茗6 小时前
【RH294知识点汇总】第 9 章 《 自动执行 Linux 管理任务 》常见问题
linux·运维·服务器
北方的流星6 小时前
华三路由器NAT配置
运维·网络·华三
数据法师7 小时前
开源情报收集工具GhostTrack深度测评:IP、手机号、用户名的合规信息查询方案
网络·网络协议·tcp/ip
丑八怪大丑8 小时前
Java网络编程
linux·服务器·网络
想成为优秀工程师的爸爸9 小时前
第三十篇技术笔记:郭大侠学UDS - 人有生老三千疾,望闻问切良方医
网络·笔记·网络协议·tcp/ip·信息与通信
橙子也要努力变强9 小时前
信号捕捉底层机制-机理篇2
linux·服务器·c++
数智工坊10 小时前
【SAM-DETR论文阅读】:基于语义对齐匹配的DETR极速收敛检测框架
网络·论文阅读·人工智能·深度学习·transformer
CQU_JIAKE10 小时前
4.28~4.30【Q】
linux·运维·服务器
先知后行。10 小时前
Linux 设备模型和platform平台
linux·运维·服务器