Read the article suggests looking back from the beginning of the first chapter
This series of articles
- Netty in Android application development in actual combat series (a) --- build a service and client
- Netty in Android application development in actual combat series (two) --- Encoder | Decoder | Handler of use
- Netty in Android application development in actual combat series (three) --- heartbeat processing | reconnection
- Netty in Android application development in actual combat series (four) --- stick package | unpacking process
- Netty in Android application development in actual combat series (five) --- Creating Web Services | as an HTTP server
First, what does stick package?
Is simply: transmitting a plurality of packets to an adherend into a package.
For example: the server sends two consecutive packets clients really only received a package (which is actually a package of two data packets), normal for the client should receive two packages. This is called the client stick package in which case you need to do the unpacking process.
Second, the general processing means of the stick package
- Use fixed-length
- Use special character segmentation ($, \ n ...)
- other
Netty also provides us several processing decoder stick package, as follows:
DelimiterBasedFrameDecoder
For stick package unpacking processing on the basis of special charactersFixedLengthFrameDecoder
Unpacking processing performed based on a fixed stick package lengthLengthFieldBasedFrameDecoder
Specifies the message length stick package unpacking process based on message headerLineBasedFrameDecoder
For stick package unpacking processing based on line breaks (\ r \ n, \ n)
Third, by the following examples to handle a stick package unpacking, where I use DelimiterBasedFrameDecoder
the decoder is then used $
as a special delimiter
First, add 3.1 to the serverDelimiterBasedFrameDecoder
/**
* 启动tcp服务端
*/
public void startServer() {
try {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
//分隔符
ByteBuf delimiter = Unpooled.copiedBuffer("$".getBytes());
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//解决粘包
pipeline.addLast(new DelimiterBasedFrameDecoder(65535, delimiter));
//添加发送数据编码器
pipeline.addLast(new ServerEncoder());
//添加解码器,对收到的数据进行解码
pipeline.addLast(new ServerDecoder());
//添加数据处理
pipeline.addLast(new ServerHandler());
}
});
//服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成
b.bind(PORT).sync();
handler.obtainMessage(0, "TCP 服务启动成功 PORT = " + PORT).sendToTarget();
Log.d(TAG, "TCP 服务启动成功 PORT = " + PORT);
} catch (Exception e) {
e.printStackTrace();
}
3.2 Since the use of special separators stick package for handling, then the need to transmit each data packet is added on the $
symbol; defined only need Encoder
to add to, the following:
public class ServerEncoder extends MessageToByteEncoder<PkgDataBean> {
private static final String TAG = "ServerEncoder";
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, PkgDataBean data, ByteBuf byteBuf) throws Exception {
//根据数据包协议,生成byte数组
byte[] bytes = {0x2A, data.getCmd(), data.getDataLength()};
byte[] dataBytes = data.getData().getBytes();
//分隔符
byte[] delimiter = "$".getBytes();
//将所有数据合并成一个byte数组
byte[] all = ByteUtil.byteMergerAll(bytes, dataBytes, new byte[]{0x2A}, delimiter);
//发送数据
byteBuf.writeBytes(all);
}
}
3.3 We write code consecutive transmit packets
//获取与客户端的连接
List<ChannelHandlerContext> channels = ServerHandler.channels;
for (ChannelHandlerContext ctx : channels) {
for (int i = 0; i < 3; i++) {
PkgDataBean bean = new PkgDataBean();
bean.setCmd((byte) 0x05);
bean.setData("粘包的数据:" + i);
bean.setDataLength((byte) bean.getData().getBytes().length);
ctx.channel().writeAndFlush(bean);
}
}
Log.d(TAG, "服务端发送了粘包数据");
Fourth, since the server has been added to the DelimiterBasedFrameDecoder
decoder, then the client also needs to add synchronization; otherwise it is impossible to resolve the abnormal data
public void connect() {
try {
NioEventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap()
// 指定channel类型
.channel(NioSocketChannel.class)
// 指定EventLoopGroup
.group(group)
// 指定Handler
.handler(new ChannelInitializer<SocketChannel>() {
//分隔符
ByteBuf delimiter = Unpooled.copiedBuffer("$".getBytes());
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new IdleStateHandler(10, 0, 0));
//解决粘包
pipeline.addLast(new DelimiterBasedFrameDecoder(65535, delimiter));
//添加发送数据编码器
pipeline.addLast(new ClientEncoder());
//添加收到的数据解码器
pipeline.addLast(new ClientDecoder());
//添加数据处理器
pipeline.addLast(new ClientHandler(NettyClient.this));
}
});
// 连接到服务端
ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(IP, PORT));
// 添加连接状态监听
channelFuture.addListener(new ConnectListener(this));
//获取连接通道
channel = channelFuture.sync().channel();
handler.obtainMessage(0, "连接成功").sendToTarget();
} catch (Exception e) {
handler.obtainMessage(0, "连接失败").sendToTarget();
Log.e(TAG, "连接失败:" + e.getMessage());
e.printStackTrace();
}
}
- Similarly, data sent by the client will write the end of the packet
$
symbols.
Fifth, now look at the effect of program execution
- The server transmits three consecutive data
- Data received by the client
For other unpacking decoder you can pick a suitable use according to their actual situation, to the basic application here in Android Netty whole would talk about it; I believe you read this four blog can also be used in actual combat Netty duck to water
This series of articles Demo Download
Welcome to exchange QQ group together