天天看点

Netty系列(四)之Netty 编解码器和粘包拆包Netty 编解码器和 handler 的调用机制TCP 粘包和拆包 及解决方案

目录

Netty 编解码器和 handler 的调用机制

基本说明

编码解码器 

解码器-ByteToMessageDecoder

TCP 粘包和拆包 及解决方案

基本介绍

TCP 粘包和拆包解决方案

Netty 编解码器和 handler 的调用机制

基本说明

1) netty 的组件设计:Netty 的主要组件有 Channel、EventLoop、ChannelFuture、ChannelHandler、ChannelPipe 等。

2) ChannelHandler 充当了处理入站和出站数据的应用程序逻辑的容器。例如,实现 ChannelInboundHandler 接口(或ChannelInboundHandlerAdapter),你就可以接收入站事件和数据,这些数据会被业务逻辑处理。当要给客户端发 送 响 应 时 , 也 可 ChannelInboundHandler 冲 刷 数 据 。 业 务 逻 辑 通 常 写 在 一 个 或 者 多 个ChannelInboundHandler 中。ChannelOutboundHandler 原理一样,只不过它是用来处理出站数据的。

3) ChannelPipeline 提供了 ChannelHandler 链的容器。以客户端应用程序为例,如果事件的运动方向是从客户端到服务端的,那么我们称这些事件为出站的,即客户端发送给服务端的数据会通过 pipeline 中的一系列ChannelOutboundHandler,并被这些 Handler 处理,反之则称为入站的。

Netty系列(四)之Netty 编解码器和粘包拆包Netty 编解码器和 handler 的调用机制TCP 粘包和拆包 及解决方案

编码解码器 

1) 当 Netty 发送或者接受一个消息的时候,就将会发生一次数据转换。入站消息会被解码:从字节转换为另一种格式(比如 java 对象);如果是出站消息,它会被编码成字节。

2) Netty 提供一系列实用的编解码器,他们都实现了 ChannelInboundHadnler 或者 ChannelOutboundHandler 接口。在这些类中,channelRead 方法已经被重写了。以入站为例,对于每个从入站 Channel 读取的消息,这个方法会被调用。随后,它将调用由解码器所提供的 decode()方法进行解码,并将已经解码的字节转发给 ChannelPipeline中的下一个 ChannelInboundHandler

解码器-ByteToMessageDecoder

关系继承图

Netty系列(四)之Netty 编解码器和粘包拆包Netty 编解码器和 handler 的调用机制TCP 粘包和拆包 及解决方案

2) 由于不可能知道远程节点是否会一次性发送一个完整的信息,tcp 有可能出现粘包拆包的问题,这个类会对入站数据进行缓冲,直到它准备好被处理. 

3) 一个关于 ByteToMessageDecoder 实例分析

Netty系列(四)之Netty 编解码器和粘包拆包Netty 编解码器和 handler 的调用机制TCP 粘包和拆包 及解决方案
Netty系列(四)之Netty 编解码器和粘包拆包Netty 编解码器和 handler 的调用机制TCP 粘包和拆包 及解决方案

TCP 粘包和拆包 及解决方案

基本介绍

1) TCP 是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使用了优化方法(Nagle 算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样做虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界的。

2)粘包和拆包发送了两个数据包给服务端,服务端两次读到到的字节数是不一样的。粘包是两个包粘合在了一起,拆包是读到了不同的数据。

TCP 粘包和拆包解决方案

1) 使用自定义协议 + 编解码器 来解决。

2) 关键就是要解决 服务器端每次读取数据长度的问题, 这个问题解决,就不会出现服务器多读或少读数据的问题,从而避免的 TCP 粘包、拆包 。