TCP 流量控制与拥塞控制

  • 滑动窗口,接收方通过通告发送方自己的可以接受缓冲区大小(这个字段越大说明网络吞吐量越高),从而控制发送方的发送速度。滑动窗口的存在是为了防止接收方过载。它规定了发送方此刻能够发送的最大数据量

但滑动窗口只考虑接收方的缓冲区,对网络链路的拥塞程度则无能为力。因此,TCP 还维护了 拥塞窗口( congestion window ),根据链路的拥塞程度来约束发送速度。

拥塞窗口跟滑动窗口类似,同样规定了发送方此刻能够发送出去的字节数,只不过它通过评估网络链路的拥塞程度,并由一定的算法计算而来的。

拥塞窗口可缩写为 cwnd ,通常以 TCP 报文段为单位,表示还能发送多少个段出去。由于 最大报文段大小 缩写为 MSS ,有时也会以 MSS 为单位来讨论。

  • 拥塞窗口(congestion window)是任何时刻内确定能被发送出去的字节数的控制因素之一,是阻止发送方至接收方之间的链路变得拥塞的手段。他是由发送方维护,通过估计链路的拥塞程度计算出来的,与由接收方维护的接收窗口大小并不冲突。

当网络链路比较顺畅时,拥塞窗口逐步增大,发送速度也就逐步提升;当网络链路发生拥塞时,拥塞窗口快速减小,发送速度急踩刹车,避免进一步压垮网络。

拥塞窗口跟滑动窗口并不冲突,前者避免压垮网络链路;后者则保证不打爆接收缓冲区。

拥塞控制

我们希望 TCP 能够根据网络链路的实时状态,自动调整发送速度,这就是 TCP 协议的 拥塞控制( congestion control )机制。拥塞控制机制细节很复杂,但原理却出奇的简单:

  • 维护拥塞窗口,限制数据发送量;
  • 根据网络当前状态,实时调节拥塞窗口:
    • 如果长时间未收到 ACK 而发生数据重传,说明网络可能拥塞,缩小拥塞窗口,降低发送速度;
    • 每收到一个有效 ACK 都增大拥塞窗口,提高发送速度,因为这通常意味着网络状态良好;

/* Can at least one segment of SKB be sent right now, according to the
 * congestion window rules?  If so, return how many segments are allowed.
 */
static inline unsigned int tcp_cwnd_test(const struct tcp_sock *tp,
					 const struct sk_buff *skb)
{
	u32 in_flight, cwnd, halfcwnd;

	/* Don't be strict about the congestion window for the final FIN.  */
	if ((TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) &&
	    tcp_skb_pcount(skb) == 1)
		return 1;

	in_flight = tcp_packets_in_flight(tp);
	cwnd = tcp_snd_cwnd(tp); //tp->snd_cwnd , Sending congestion window
	if (in_flight >= cwnd)
		return 0;

	/* For better scheduling, ensure we have at least
	 * 2 GSO packets in flight.
	 */
	halfcwnd = max(cwnd >> 1, 1U);
	return min(halfcwnd, cwnd - in_flight);
}


static inline unsigned int tcp_left_out(const struct tcp_sock *tp)
{
	return tp->sacked_out + tp->lost_out;
}

/* This determines how many packets are "in the network" to the best
 * of our knowledge.  In many cases it is conservative, but where
 * detailed information is available from the receiver (via SACK
 * blocks etc.) we can make more aggressive calculations.
 *
 * Use this for decisions involving congestion control, use just
 * tp->packets_out to determine if the send queue is empty or not.
 *
 * Read this equation as:
 *
 *	"Packets sent once on transmission queue" MINUS
 *	"Packets left network, but not honestly ACKed yet" PLUS
 *	"Packets fast retransmitted"
 */
static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
{
	return tp->packets_out - tcp_left_out(tp) + tp->retrans_out;
}

ref

拥塞窗口,TCP的拥塞控制机制 | 小菜学网络

tcp - TCP之拥塞窗口_个人文章 - SegmentFault 思否

https://zh.wikipedia.org/wiki/TCP%E6%8B%A5%E5%A1%9E%E6%8E%A7%E5%88%B6

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值