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的时候

重传

定时机制

用户控制

相关推荐
勿忘,瞬间2 小时前
网络编程套接字
运维·服务器·网络
二等饼干~za8986682 小时前
源码可控:云罗 GEO 源头工厂,开源搭建 + 二次开发全链路解决方案
服务器·开发语言·开源·php·音视频·ai-native
@insist1232 小时前
网络工程师-网络安全基础体系:软考核心考点与合规框架全解析
网络·网络工程师·软考·软件水平考试
zhanghongbin012 小时前
本地持久化:网络故障数据保护
服务器·网络·php
刘~浪地球2 小时前
数据库与缓存--分库分表实战指南
网络·数据库·缓存
funnycoffee1232 小时前
华为USG防火墙的HRP逃逸是什么机制?
运维·服务器·网络·华为usg
念恒123063 小时前
Linux初识
linux·服务器·c++
开开心心就好3 小时前
能把网页藏在Word里的实用摸鱼工具
linux·运维·服务器·windows·随机森林·逻辑回归·excel
Bruce_Liuxiaowei3 小时前
技嘉Aorus主板Win10引导故障深度修复:从网络重置到注册表移植
服务器·网络·windows·microsoft