TCP 编程底层都有粘包和拆包机制,因为我们在C/S这种传输模型下,以TCP协议传输的时候,在网络中的皮竖byte其实就像是河水,TCP就像一个搬运工,将这流水从一端转送到另一端,这时又分两种情况:
下面通过 Netty 重现 TCP 粘包和拆包现象。
其中关键的代码如下
从上面的案例可以发现当出现 TCP 粘包和拆包现象后会出现下面的问题:
由于 TCP 粘包和拆包现象会导致不能正确区分数据的头尾,那么解决的办法也挺简单的,通过 特殊字符串 来分隔消息体或者使用 定长消息 就能够正确区分数据的头尾。
目前的主流拍握空解决方式有以下几种:
Netty 中也提供了基于分隔符实现的半包解码器和定长的半包解码器:
使用 DelimiterBasedFrameDecoder 可以确保收到的数据会自动通过 自定义的分隔符 进行分隔。发送的时候消息的后袭瞎面只需要增加上 自定义的分隔符 即可。
TCP协议下的粘包与拆包,如何解决一、粘包、拆包1.1 粘包原因1.1.1 滑动窗口1.1.2 Nagle算法1.1.3 应用层原因1.2 拆包原因1.2.1 滑动窗口1.2.2 MSS限制1.2.3 应用层原因1.2 Netty提供的解决方案二、自定义协议解决粘包、拆包2.1 自定义协议要素
因为TCP/IP在起初,所有的请求是串行化的,之后做成了滑动局则窗口的返腊喊概念。那么在接收方,如果接收不及时且窗口大小足够大,就可能出现粘包的情况。
因为每次数据发送的时候,都需要加上消息头等特殊数据,TCP与IP协议分别会加20Byte数据,因此哪怕只是发送1Byte数据,最终接收方还是会接收到41Byte;在这样的背景下,Nagle算法可能会将多个数据包合并在一起发送。
接收方ByteBuf设置太大(Netty默认为1024Byte),因此如果客户端发送的报文都非常小,抛开上述 1.1.1.1 中的原因不谈,光在Netty这一处也非常容易出现粘包现象
假设接收方的窗口只剩128Bytes,发送方的报文大小是256Bytes,这时放不下了,只能先发送前128Bytes,等待ack后,窗口有剩余空间了才会发送剩余部分,这就导致了拆包
当发送数据超过MSS限制后,会将数据切分发送,而这个MSS是根据不同类型网卡的限制来看,譬如某笔记本漏野网卡可以发送1500Byte,除去一次数据包中的TCP/IP固定40Byte外,真正的数据也只能发送1460Byte。
Netty中ByteBuf设置的大小小于数据包大小。
未完待续... ...
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)