Nagle算法

Nagle算法的目的是避免TCP发送大量的小数据包。TCP在接收到前一个小段的ACK消息之前,一直保存

小数据包。

Nagle算法通常在实现时要求做到,如果存在任何未确认的数据就不能发送小数据包。

BSD的实现是允许在空闲链接上发送大的写操作剩下的最后的小段。

 

Nagle算法是silly window syndrome(SWS)预防算法的一个半集。SWS算法预防发送少量的数据,

Nagle算法是其在发送方的实现,而接收方要做的时不要通告缓冲空间的很小增长,不通知小窗口,除非

缓冲区空间有显著的增长。这里显著的增长定义为完全大小的段(MSS)或增长到大于最大窗口的一半。

 

linux中的Nagle检测源码

 

/* 该函数返回1表示还有小包没有确认

* snd_sml保存的是最近发送的小包的序号

*/

static inline int tcp_minshall_check(const struct tcp_sock *tp)
{
 return after(tp->snd_sml, tp->snd_una) &&
  !after(tp->snd_sml, tp->snd_nxt);
}

 

/* Return 0, if packet can be sent now without violation Nagle's rules:
 * 1. It is full sized.
 * 2. Or it contains FIN. (already checked by caller)
 * 3. Or TCP_NODELAY was set.
 * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
 *    With Minshall's modification: all sent small packets are ACKed.

* 反之,Nagle算法使用的情况是满足以下条件

* 1 数据包小于MSS

* 2 TCP_CORK设置了,或,没设置TCP_NODELAY并且上一个小包没有确认
 */
static inline int tcp_nagle_check(const struct tcp_sock *tp,
      const struct sk_buff *skb,
      unsigned mss_now, int nonagle)
{
 return (skb->len < mss_now &&
  ((nonagle & TCP_NAGLE_CORK) ||
   (!nonagle && tp->packets_out && tcp_minshall_check(tp))));
}

 

/* Return non-zero if the Nagle test allows this packet to be
 * sent now.
 */
static inline int tcp_nagle_test(struct tcp_sock *tp, struct sk_buff *skb,
     unsigned int cur_mss, int nonagle)
{
 /* Nagle rule does not apply to frames, which sit in the middle of the
  * write_queue (they have no chances to get new data).
  *
  * This is implemented in the callers, where they modify the 'nonagle'
  * argument based upon the location of SKB in the send queue.
  */
 if (nonagle & TCP_NAGLE_PUSH)
  return 1;

 /* Don't use the nagle rule for urgent data (or for the final FIN).
  * Nagle can be ignored during F-RTO too (see RFC4138).
  */
 if (tcp_urg_mode(tp) || (tp->frto_counter == 2) ||
     (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN))
  return 1;

 if (!tcp_nagle_check(tp, skb, cur_mss, nonagle))
  return 1;

 return 0;
}
对于紧急数据以及FIN包,F-RTO包,要忽略NAGLE。

 

nagle算法的一个问题是会与TCP的延迟确认机制发生冲突。举例如下:

如果客户端发送一个请求,但是却以2个数据包(第一个大概是包头信息)的方式发送。

当第一个数据包发送后,Nagle机制启用,不能发送第2个数据包,除非得到对方的ACK确认;

但是由于TCP的机制是延迟确认,也就是如果当前没有数据发送捎带ACK的话,就在200ms(linux)

发送ACK。这样造成的延迟是很客观的。

 

解决的办法是禁止nagle算法,不过这显然是有失本意的(大量小数据包的发生);

所以在发送数据的时候要尽量使用聚集写(writev)。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值