专栏首页游戏开发司机(十二)深入浅出TCPIP之Nagle算法

(十二)深入浅出TCPIP之Nagle算法

TCP的数据流大致可以分为两类,交互数据流与成块的数据流。交互数据流就是发送控制命令的数据流,比如relogin,telnet,ftp命令等等;成块数据流是用来发送数据的包,网络上大部分的TCP包都是这种包。

很明显,TCP在传输这两种类型的包时的效率是不一样的,因此为了提高TCP的传输效率,应该对这两种类型的包采用不同的算法。

总之,TCP的传输原则是尽量减少小分组传输的数量。

Nagle算法分析

Nagle算法主要用来预防小分组的产生。在广域网上,大量TCP小分组极有可能造成网络的拥塞。

Nagle时针对每一个TCP连接的。它要求一个TCP连接上最多只能有一个未被确认的小分组。在改分组的确认到达之前不能发送其他小分组。TCP会搜集这些小的分组,然后在之前小分组的确认到达后将刚才搜集的小分组合并发送出去。

有时候我们必须要关闭Nagle算法,特别是在一些对时延要求较高的交互式操作环境中,所有的小分组必须尽快发送出去。

我们可以通过编程取消Nagle算法,利用TCP_NODELAY选项来关闭Nagle算法。

来看看Nagle大致的逻辑:

if 有数据要发送:

if 可用窗口大小 >= MSS and 可发送的数据 >= MSS:

立刻发送MSS大小的数据

else :

if 有未确认的数据:

将数据放入缓存等待接收ACK

else:

立刻发送数据

通过上面的逻辑可以看到,如果是大量数据需要发送,大部分情况都可以填满一个MSS(也就不存在"小包"的问题),是不需要等待一个未确认包的。

Nagle算法是时代的产物,因为当时网络带宽有限。而当前的局域网、广域网的带宽则宽裕得多,所以目前的TCP/IP协议栈默认将Nagle算法关闭

long noDelay = 1;
setsockopt(m_hSocket, IPPROTO_TCP, TCP_NODELAY,(LPSTR)&noDelay, sizeof(long));

noDelay为1打开nagle算法,为0禁用nagle算法。

延迟确认机制(TCP delayed acknowledgment)

wiki的解释https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment

1989 RFC 1122定义,全名Delayed Acknowledgment,简称延迟ACK,翻译为延迟确认。

与Nagle算法一样,延迟ACK的目的也是为了减少网络中传输大量的小报文数,但该报文数是针对ACK报文的。

一个来自发送端的报文到达接收端,TCP会延迟ACK的发送,希望应用程序会对刚刚收到的数据进行应答,这样就可以用新数据将ACK捎带过去。

当Nagle算法遇到Delayed ACK

在一个有数据传输的TCP连接中,如果只有数据发送方启用Nagle算法,在其连续发送多个小报文时,Nagle算法机制会减少网络中的小报文数量。这就意味着,同样传输相同大小的应用数据,在网络上的报文个数却不同。

举个例子,发送端需要连续发送5个写操作(应用程序将数据写入到缓冲池的动作)的小报文,首先发送第一个,由于Nagle算法的作用,在未收到第一个报文确认前,发送端在等待写操作的同时进行读操作,接收端并未启用延迟确认(视TCP delay ACK时间为0),尽管刚收到该报文就发出确认,但由于网络延时的原因,在收集齐另外4个小报文后,发送方才收到了第一个报文的ACK,则后面的4个报文会一起发送出去(大小未超过MSS),接收端再次ACK。

在上述发送5个小报文的过程中,只用了4个报文就实现了。但如果发送端未启用Nagle算法,完成整个过程则至少需要8个报文或10个报文才能实现,这里接收端未启用延迟确认,如下图所示。启用Nagle算法和未启用Nagle算法的场景中,从完成数据发送的时间来看,未启用Nagle算法的方式花费的时间会更长一些,如下图所示。这里基本看到了Nagle算法的好处了。

还是上述数据传输场景,发送端未启用Nagle算法,但接收端延迟确认默认时间为200ms,来看看这时的情况。RFC 1122规定,Delayed ACK对单个的小报文可以延长确认的时间,但不允许有两个连续的小报文不被确认。所以,当发送端连续发送两个报文后,接收端必须给予确认。这时的数据传输情况如下图,只有当第5个报文到达后,接收端由于延迟确认机制,会导致200ms的延时存在。

接下来看看,当Nagle算法遇到Delayed ACK时会是什么情况。按照常理推断,两种深思熟虑的功能设计,应该是1+1>2的效果。具体如何,还是请事实说话。

先继续看上面的假设场景,该场景要求发送端向接收端发送5个连续的写操作数据,但网络延时较大,同时发送端启用Nagle算法,接收端Delayed ACK默认为200ms。

发送方先发出一个小报文,接收端收到后,由于延迟确认的机制,等待发送方的下一个报文到达。而发送方由于Nagle算法机制,在未接收到第一个报文的确认前,不会发送已读取到的报文。 在这种场景下,暂不考虑应用处理时间,完成整个数据传输所需时间为2RTT+400ms,貌似情况不是特别糟糕。

如果上述其他条件不变,发送方应用写操作延时稍微变大,或发送端的应用操作延时稍大,我们再看看,完成这个操作的延时情况。

发送方先发出一个小报文,接收端收到后,由于延迟确认的机制,等待发送方的下一个报文到达。由于发送方应用数据写操作延时较大,在经过RTT+200ms后,读取到了下一个需要发送的内容,此时接收到了第一个报文的确认,而网络中未有没被确认的报文,发送方需要再将第二个小报文发送出去,以此类推,直到最后一个小报文被发送,且接收到该报文的确认,此时整个数据传输过程完成。

在这种情景下,完成整个数据传输所需时间则为5RTT+5*200ms,明显增大了不少。如果相同情境下,有成千上万的小报文发送,则整体使用时间相当可观了。

在实际情况下,如果发送方程序做了一系列的写、写、读操作的现象,这样的操作都会触发Nagle和延迟ACK算法之间的交互作用,应该尽量避免。

应用场景:

1.对于实时性要求很高的交互上,我们不能使用nagle算法,比如FPS射击类PVP对抗类游戏,或者MMO类的对实时要求很高的游戏开发来说是显而易见需要禁掉的,因为假如玩家的一次移动,或者状态同步到服务器,加上协议头,包体不会太大,如果使用Nagle算法,后果将是,客户端本来完成一次射击动作,或者释放技能的动作却因为此算法,因为发送包体较小,被放置到缓冲区,等其他包到达可发送了才一起发送到服务器端,那么你不坑队友,还能有谁你?

2.对于发送接收的业务,但是每次发送的包体又是很小的,对于业务的实时性不是非常强的,我们可以使用nagle算法,将小包组成大包统一发送,减少交互次数。

本文分享自微信公众号 - 游戏开发司机(gamerdev),作者:高司机

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • (一)深入浅出TCPIP之理解TCP报文格式和交互流程

    TCP和UDP是完全迥异的传输层协议,被设计为做不同的事情。二者的共性是都使用IP作为其网络层协议。TCP和UDP之间的主要差别在于可靠性。TC...

    用户3479834
  • (十五)深入浅出TCPIP之Hello CDN

    CDN 其实是 Content Delivery Network 的缩写,即“内容分发网络”。CDN是将媒体资源,动静态图片(Flash) ,HTML, CSS...

    用户3479834
  • (七)深入浅出TCPIP之深入浅出TCPIP之TCP重传机制

    注意,接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注...

    用户3479834
  • (十七)深入浅出TCPIP之HTTP和HTTPS

    超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和...

    用户3479834
  • (十一)深入浅出TCPIP之TCP粘包问题

    粘包拆包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输层都有可能发生。我们日常的网络应用开发大都在传输层进行,由于UDP有消息保护...

    用户3479834
  • (十三) 深入浅出TCPIP之setsockopt参数详解

    在socket编程中我们会经常用到setsockopt这个函数,那么本节我们将对这个函数的参数和使用做说明:

    用户3479834
  • (十六)深入浅出TCPIP之UDP打洞原理

    由于Internet的快速发展 IPV4地址不够用,不能每个主机分到一个公网IP 所以使用NAT地址转换。

    用户3479834
  • (十八)深入浅出TCPIP之epoll的一些思考

    在linux的网络编程中,很长的时间都在使用select来做事件触发。在linux新的内核中,有了一种替换它的机制,就是epoll。相比于 select,epo...

    用户3479834
  • 深入浅出KNN算法(二) sklearn

    上次介绍了KNN的基本原理,以及KNN的几个窍门,这次就来用sklearn实践一下KNN算法。

    py3study
  • 海量之道系列文章之弱联网优化 (四)

    我们需要有一条(相对)快速、(相对)顺畅、(相对)稳定的网络通道承载业务数据的传输,这条路的最好是传输快、不拥堵、带宽大、收费少。如何才能做到快链路,且听下面分...

    樊华恒
  • (十)深入浅出TCPIP之网络阻塞和非阻塞

    阻塞和非阻塞 强调的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞...

    用户3479834
  • (二十二)深入浅出TCPIP之实战篇—用c++开发一个http服务器

    在当前的网络编程专栏前十几篇文章里,我已经说明了TCPIP常用的一些原理,那么接下来我将逐步进入到实战编程阶段:

    用户3479834
  • 提高 Linux 上 socket 性能

    在开发 socket 应用程序时,首要任务通常是确保可靠性并满足一些特定的需求。利用本文中给出的 4 个提示,您就可以从头开始为实现最佳性能来设计并开发 soc...

    一见
  • (六)深入浅出TCPIP之TCP拥塞控制

    当网络中存在过多的数据包时,网络的性能就会下降,这种现象称为拥塞。 在网络发生拥塞时,会导致吞吐量下降,严重时会发生“拥塞崩溃" (congestion clp...

    用户3479834
  • (五)深入浅出TCPIP之TCP流量控制

       我们都知道TCP是一种可靠的,面向连接的传输层协议。我们总是希望TCP能够传输的数据越快越好。如果存在这样一种情况,发送方数据发送的非常快,而且接收方耗尽...

    用户3479834
  • 《计算机网络系列》——TCP粘包很难么,我为何屡屡受挫??

    逛论坛看到一个帖子,标题说自己在学习网络模型,经常有人提到TCP粘包问题,他笑了。这个帖子讨论人数还挺多的。既然看到,顺便解释下这个问题。 TCP问题也算是计...

    龙跃十二
  • Linux 2.6.16 TCP 连接速度异常的问题分析

    发现访问公司某些业务时,速度非常不稳定,并且整体慢于竞争对手。分析认为 SESU10 母盘上内核 TCP 拥塞控制算法和 Windows 的 Ack 频率控制的...

    余子军
  • (九)深入浅出TCPIP之网络同步异步

    同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)。

    用户3479834
  • 深入浅出聚类算法

    聚类问题是机器学习中无监督学习的典型代表,在数据分析、模式识别的很多实际问题 中得到了应用。在本文中,SIGAI 将为大家深入浅出的介绍聚类问题的定义以及各种典...

    SIGAI学习与实践平台

扫码关注云+社区

领取腾讯云代金券