(四)什么是TCP拆包、粘包?如何解决?

一、TCP协议

TCP是一个面向字节流的协议,它的性质是流式的,所以它并没有分段。就像水流一样,你没法知道什么时候开始,什么时候结束。

所以他会根据当前的套接字缓冲区的情况进行拆包或是粘包。

(四)什么是TCP拆包、粘包?如何解决?_第1张图片

发送端的字节流都会先传入缓冲区,再通过网络传入到接收端的缓冲区中,最终由接收端获取。

 

 

二、拆包、粘包

当我们发送两个完整包到接收端的时候:

(四)什么是TCP拆包、粘包?如何解决?_第2张图片

正常情况会接收到两个完整的报文。

 

但也有以下的情况:

(四)什么是TCP拆包、粘包?如何解决?_第3张图片

接收到的是一个报文,它是由发送的两个报文组成的,这样对于应用程序来说就很难处理了(这样称为粘包)。

 

(四)什么是TCP拆包、粘包?如何解决?_第4张图片

还有可能出现上面这样的,虽然收到了两个包,但是里面的内容却是互相包含,对于应用来说依然无法解析(这样称为拆包)。

 

 

三、解决方式

对于这样的问题只能通过上层的应用来解决,常见的方式有:

  • 在报文末尾增加换行符表明一条完整的消息,这样在接收端可以根据这个换行符来判断消息是否完整。
  • 将消息分为消息头、消息体。可以在消息头中声明消息的长度,根据这个长度来获取报文(比如808协议)。
  • 规定好报文长度,不足的空位补齐,取的时候按照长度截取即可。

以上的这些方式我们在Netty的pipline中加入对应的解码器都可以手动实现。

但其实Netty已经帮我们做好了,完全可以开箱即用。

比如:

  • LineBasedFrameDecoder可以基于换行符解决。
  • DelimiterBasedFrameDecoder可以基于分隔符解决。
  • FixedLengthFrameDecoder可以指定长度解决。

 

上面提到的其实就是在解码中进行操作,我们也可以自定义自己的拆、粘包工具。

编解码的主要目的就是为了可以编码成字节流用于在网络中传输、持久化存储。

java中也可以实现serializable接口来实现序列化,但由于它性能等原因在一些RPC调用中用的很少。

Google Protocol Buffer(protobuf)则是一个高效的序列化框架。

下载安装protobuf后,可以定义自己的协议格式,自动生成自定义协议格式java代码(编解码都封装好了)。

Netty已经自带了对protobuf的编解码器,只需要在pipline中添加即可。

 

 

具体原理及使用请前往https://crossoverjie.top/2018/08/03/netty/Netty(3)TCP-Sticky/,本文学习借鉴自此文章。

你可能感兴趣的:(netty)