1. effect
- LengthFieldBasedFrameDecoder The decoder is based on length The value of the field dynamically splits the received ByteBuf, Decoding binary messages ( Contains header : The length of the message stored in the header ) when , This decoder is particularly useful
2. Argument parsing
2.1 Simple to build netty Communications
2.1.1client
package cn.itbin.decode.client;
import cn.itbin.client.TelnetClientInitializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* @author chenxiaogao
* @className Client
* @description TODO
* @date 2020/11/7
**/
public class Client {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8023"));
public static void main(String[] args) throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
;
// Start trying to connect
Channel ch = b.connect(HOST, PORT).sync().channel();
String request = "HELLO, WORLD";
ByteBuf buffer = Unpooled.buffer();
buffer.writeShort(request.length());
buffer.writeBytes(request.getBytes());
ch.writeAndFlush(buffer);
} finally {
group.shutdownGracefully();
}
}
}
2.1.2server
- server
package cn.itbin.decode.server;
import cn.itbin.server.TelnetServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.util.Arrays;
/**
* @author chenxiaogao
* @className Server
* @description TODO
* @date 2020/11/7
**/
public class Server {
static final int PORT = Integer.parseInt(System.getProperty("port", "8023"));
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ServerInitializer());
b.bind(PORT).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
- ServerInitializer
package cn.itbin.decode.server;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
/**
* @author chenxiaogao
* @className ServerInitializer
* @description TODO
* @date 2020/11/7
**/
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2));
pipeline.addLast(new ServerHandler());
}
}
- ServerHandler
package cn.itbin.decode.server;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.nio.charset.Charset;
/**
* @author chenxiaogao
* @className ServerHandler
* @description TODO
* @date 2020/11/7
**/
public class ServerHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
int length = msg.readableBytes();
System.out.println(" Total request length = " + length);
// First read the length bits of two bytes
short len = msg.readShort();
System.out.println(" The length of the requested newspaper style = " + len);
System.out.println(" After reading two bytes ByteBuf = " + msg);
// Read the message content
byte[] bytes = new byte[len];
msg.readBytes(bytes, 0, len);
String request = new String(bytes, Charset.forName("GBK"));
System.out.println(" Style of request newspaper = " + request);
}
}
2.2 Parameters,
2.2.1 new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2)
lengthFieldOffset = 0
lengthFieldLength = 2
lengthAdjustment = 0
initialBytesToStrip = 0 (= do not strip header)
BEFORE DECODE (14 bytes) AFTER DECODE (14 bytes)
+--------+----------------+ +--------+----------------+
| Length | Actual Content |----->| Length | Actual Content |
| 0x000C | "HELLO, WORLD" | | 0x000C | "HELLO, WORLD" |
+--------+----------------+ +--------+----------------+
Suppose the first two bytes of the request message are the length of the message style
And hope that the server can receive the complete message
Then add the following decoder
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2));
This constructor is called when the decoder is added
public LengthFieldBasedFrameDecoder(
int maxFrameLength,
int lengthFieldOffset, int lengthFieldLength) {
this(maxFrameLength, lengthFieldOffset, lengthFieldLength, 0, 0);
}
Then the actual parameter is
maxFrameLength:Integer.MAX_VALUE( The maximum length of the overall message , Including message header and message style )
lengthFieldOffset:0( The starting index of the length field )
lengthFieldLength :2( The length of the length field )
lengthAdjustment : 0
initialBytesToStrip :0
1. Assemble the request body :
String request = "HELLO, WORLD";
// Create a byte buffer
ByteBuf buffer = Unpooled.buffer();
// Write two bytes of the length of the message style , The length is 12
buffer.writeShort(request.length());
// Write in newspaper style
buffer.writeBytes(request.getBytes());
// send out
ch.writeAndFlush(buffer);
The actual request body is :
Information : [id: 0x87221f3a, L:/127.0.0.1:52524 - R:/127.0.0.1:8023] WRITE: 14B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+------------------------