在工作中和硬件进行交互的时候,硬件一般选用的都是16进制的报文进行socket传输。在使用Netty的“DelimiterBasedFrameDecoder”处理16进制的固定结束符的时候需要注意下它和普通字符串处理的区别,下面就简单写个demo模拟下处理方式。
public class DelimiterServer {
public static void main(String[] args) {
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
try {
ServerBootstrap server = new ServerBootstrap();
server.group(boss, worker).channel(NioServerSocketChannel.class).childHandler(new DelimiterInitializer());
ChannelFuture channelFuture = server.bind(9999).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
}
pipeline的处理
public class DelimiterInitializer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, false, Unpooled.wrappedBuffer(new byte[]{0x16})));
pipeline.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS));
pipeline.addLast(new DelimiterHandler());
}
}
这里需要注意的就是“DelimiterBasedFrameDecoder”的处理,这里截取的就是 16 进制 16 结尾的数据。
Unpooled.wrappedBuffer(new byte[]{0x16}))
可以看到16进制的16转换成字节数组之后成为了【22】,所以Netty提供的这个解码器还是按照字节数组进行数据截取的。
编写需要处理业务逻辑的handler来验证解析器设置的是否正确:
public class DelimiterHandler extends SimpleChannelInboundHandler<ByteBuf> {
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteBuf.readableBytes(); i++) {
sb.append(String.format("%02X", byteBuf.getByte(i)));
}
System.out.println(sb.toString());
}
}
打开客户端进行测试,这里需要设置发送的报文为16进制报文:
可以看到服务器能够准确解析到我们发送的报文。现在我们把结束符换成 22再试试效果:
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, false, Unpooled.wrappedBuffer(new byte[]{0x22})));
因为我发送报文包含两个“22”因此这里会进行粘包的处理,从控制台能够看到也是处理成功的。因此后面具体的报文解析需要根据自己的业务进行调整即可,Netty为我们提供的固定结束符解析器还是十分强大的。
原创文章,作者:速盾高防cdn,如若转载,请注明出处:https://www.sudun.com/ask/77932.html