美文网首页异步编程NIO(Netty, Vert.x, Akka和Node.js)
关于TCP收到数据粘包问题——Nagle算法

关于TCP收到数据粘包问题——Nagle算法

作者: XDgbh | 来源:发表于2018-07-11 23:07 被阅读103次
  • 在一个项目中,要在TCP连接的客户端和服务器之间发送json形式的数据。遇到了一个问题,有时候数据发送端连续多次调用send()函数发送多条json字符串时,接收端用recv()函数接收一条数据是一个组合多条json的大字符串,并不是期望的收到多条分割开的json字符串。这就是TCP的粘包问题。
  • 这就导致在使用cJSON_Parse()函数对json字符串进行解析时,只能解析出第一条完整的json,而后面的就丢弃了。这种情况对于每条json是一条命令来说,是很糟糕的。
  • 其实这种每条json是一个命令的业务需求,使用UDP来发送数据,就不会发生粘包问题。UDP是数据报传输协议,顾名思义其就是每次发送一个数据报,不会进行多条的封装拼凑再集体发送。

在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须自己提供科学的拆包机制。

对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。所以UDP不会出现粘包问题。
https://www.cnblogs.com/kex1n/p/6502002.html
TCP通信粘包问题分析和解决(全)
====================================================================

TCP的Nagle算法和延迟ACK

  • Nagle算法的操作过程请参看Wiki,它减少了大量小包的发送,实际上就是基于小包的停-等协议。在等待已经发出的包被确认之前,发送端利用这段时间可以积累应用下来的数据,使其大小趋向于增加。这是避免糊涂窗口综合症的一种有效方法,请注意,糊涂窗口指的是接收端的糊涂,而不是发送端的糊涂,接收端不管三七二十一得通告自己的接收窗口大小,丝毫不管这会在发送端产生大量小包。然而发送端可以不糊涂,你通告你的,我就是不发,你糊涂我不糊涂,你不断通告很小的数值,我不予理睬,我有自己的方法,直到收到已经发出包的ACK才会继续发送,这就是Nagle算法的糊涂抵制方案。
  • 治疗糊涂窗口综合症有两种方式,一种是“你糊涂我不糊涂”的方式,即上述的Nagle算法的方式,另外一种是“治疗接收端的糊涂”的方式,其中一种机制是延迟ACK(还有其它机制,比如不发送小窗口通告等)。可以看出,这两种方式中都在试图减少包的发送量,二者殊途同归的解决了同一问题,对于发送方而言,不理会接收端的小窗口通告等于说不马上发送小包,小包得以有时间积累成大包,对于接收方而言,延迟ACK可以拖延ACK发送时间,进而延迟窗口通告,在这段时间内,接收窗口有机会进一步(由于应用程序处理)放大。单独理解这两种方式都是简单的,但是一旦它们混在一起使用,情况就会非常不幸!因为...
  • Nagle算法和延迟ACK作用在方向相反的数据包和针对该数据包的确认包上,因此它们的作用力会相悖,结果就是谁也不能发包。就像一根绳子上拴两只青蛙一样,被对方牵制谁也跑不了!关键点在于,小包的发送依赖于ACK,然而延迟ACK阻止了ACK的即时发送,形成了僵持状态。本来只是为了减少网络上小包的数量(再次强调Nagle算法以及延迟ACK的目的,注意,糊涂窗口综合症只是网络上小包泛滥的原因之一!),却人为引入了大量的延迟!
  • 此处有一个通用的解释,Nagle算法的小包发送依赖于接收端对小包得快速确认,因此接收端对待ACK而言,应该朝着延迟ACK相反俄方向用力,即快速ACK;相对的,如果在接收端启用了延迟ACK,发送端就应该不断发送数据包,不管是大包还是小包(不考虑稍带ACK的影响),因为发送端已经不能指望接收端正常ACK数据包了,即发送端应该禁掉Nagle算法。以上解释背后的思想就是数据包和ACK包是相关的,力应该往一个方向使,一边拉另一边就要推,如果两边都拉,力就会抵消掉,陷入僵持。不幸点或者说悲哀的地方在于,Nagle算法和延迟ACK机制都是“拉方案”!划船的人都知道,划桨手有两种座位布局,要么超同一个方向,要么面朝不同的方向,后者和TCP数据包和ACK很类似,要想船往前走,必须朝一个方向划,虽然他们面朝相反的方向。

https://blog.csdn.net/dog250/article/details/21303679
再次谈谈TCP的Nagle算法与TCP_CORK选项

https://blog.csdn.net/wdscq1234/article/details/52432095
TCP-IP详解:Nagle算法

相关文章

  • 关于TCP收到数据粘包问题——Nagle算法

    在一个项目中,要在TCP连接的客户端和服务器之间发送json形式的数据。遇到了一个问题,有时候数据发送端连续多次调...

  • TCP之Nagle、Cork、Delay ACK(延迟确认)

    [TOC] 参考资料 TCP协议中的Nagle算法 TCP中的Nagle算法 Linux下TCP延迟确认(Dela...

  • 详解Socket编程---TCP_NODELAY选项

    Nagle算法描述 Socket编程中,TCP_NODELAY选项是用来控制是否开启Nagle算法,该算法是为了提...

  • netty的编解码

    什么是拆包/粘包 TCP 粘包/拆包 半包:读取的数据不是一个数据包粘包:读取的数据超过一个数据包 粘包问题的解决...

  • JAVA-每日一面 2022-01-25

    什么是 TCP 粘包/拆包以及TCP 粘包/拆包的解决办法 TCP 粘包/拆包1、要发送的数据大于 TCP 发送缓...

  • HTTP连接管理

    Http事务的时延:(1)TCP建立连接握手(2)TCP慢启动拥塞控制(3)数据聚集的Nagle算法(4)用于捎带...

  • day32-粘包问题和报头的定制

    粘包问题 TCP协议作为流式协议,只有TCP协议存在粘包问题。 发送端可以是一K一K地发送数据,而接收端的应用程序...

  • 网络部分

    TCP 粘包/拆包 问题 问题定义:TCP 是一个面向字节流的协议,并不理解上层发来的完整的数据包(注意,不是数据...

  • 丢包?粘包?为什么?怎么办

    tcp粘包和upd丢包 先说粘包的原因: 1.要发送的数据小于TCP发送缓存区的大小,TCP将多次写入缓冲区的数据...

  • Netty之解决TCP粘包拆包(自定义协议)

    1、什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据。TCP通讯为何存在粘包...

网友评论

    本文标题:关于TCP收到数据粘包问题——Nagle算法

    本文链接:https://www.haomeiwen.com/subject/bqnhpftx.html