Netty自定义DelimiterBasedFrameDecoder [英] Netty Custom DelimiterBasedFrameDecoder

查看:193
本文介绍了Netty自定义DelimiterBasedFrameDecoder的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的公司正在探索使用Netty Framework实施消息路由器的可能性.将要路由的消息来自许多不同的来源,并且都有各自的格式.在大多数情况下,消息采用XML格式,其中包含包含正文长度的标头.但是,我们有一个供应商,其信息是不同的,并且不包含正文的长度.

My company is exploring the possibility of using the Netty Framework to implement a message router. The messages that it will be routing come from many different sources and all have their own formats. In most cases the messages are in XML which includes a header that contains the body length. However we have one vendor who's message are different and don't contain the length of the body.

此供应商消息包含HEADER,BODY和TRAILER. 标头是1个字节,是STX(0x02) 主体长度可变 尾部为2个字节,其中包含一个ETX(0x03)和一个LRC.

This one vendors message contains a HEADER, BODY and TRAILER. The header is 1 byte and is an STX (0x02) The body is variable length The trailer is 2 bytes which contain an ETX(0x03) followed by an LRC.

因此,典型的消息可能看起来像:

So a typical message might look like:

STX   BODY   ETX  LRC
02  37000000 06   18

我们最初使用DelimiterBasedFrameDecoder将ETX定义为定界符,但是当我们这样做时,我们会松开消息中的LRC字节.结果,LRC最终成为我们解码的下一条消息的第一个字节.有没有一种方法可以使用DelimiterBasedFrameDecoder并读取ETX分隔符之后的一个字节?

We initially used the DelimiterBasedFrameDecoder defining the ETX as the delimiter, however when we do that we loose the LRC byte that is part of the message. As a result the LRC ends up being the first byte of the next message that we decode. Is there a way to use the DelimiterBasedFrameDecoder and read one byte past the ETX delimiter?

此外,当我们将响应发送回源时,源将随后向我们发送一个ACK,我们也必须使用ACK来响应.

Further, when we send a response back to the source, the source will then send us an ACK which we have to respond to with an ACK as well.

我认为我们需要一个定制的解码器来读取该字节,如果它是ACK,则它会通知下一个处理程序,否则它将继续读取,直到它从ETX读取了1个字节,然后将该消息发送到下一个处理程序.看起来合理吗?在Netty中,是否有更好的方法或者我想使用的解码器代替DelimiterBasedFraneDecoder?

I am thinking that we need a custom decoder that reads the byte, if it is an ACK then it notifies the next handler, otherwise it continues reading until it reads 1 byte past the ETX and then sends that message on to the next handler. Does that seem reasonable? Is there a better way or is there a decoder in Netty that I might want to use instead of of the DelimiterBasedFraneDecoder?

对此我能提供的任何帮助,将不胜感激!

Any help that I can get on this is appreciated!

谢谢 蒂姆

因此,在诺曼的建议下,我创建了以下解码器:

So at Norman's suggestion I created the following decoder:

public class MyDecoder extends DelimiterBasedFrameDecoder{

    public MyDecoder(int maxFrameLength, boolean stripDelimiter, ByteBuf delimiter) {
        super(maxFrameLength, stripDelimiter, delimiter);
        this.setSingleDecode(true);
    }

    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
        Object frame = super.decode(ctx, buffer);
        ByteBuf bufFrame = null;

    if(frame instanceof ByteBuf){
        bufFrame = (ByteBuf)frame;

        }else{
            System.out.println("OBJECT TYPE: " + frame.getClass().getSimpleName());
        }

        byte lrc = buffer.readByte();
        bufFrame.writeByte(lrc);
        return bufFrame;
   }

    public MyDecoder(int maxFrameLength, ByteBuf delimiter) {
        super(maxFrameLength, delimiter);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        System.out.println("VERIFONE DECODER READY");
    }
}

我的处理程序使用以下命令初始化...

My Handlers are initialized with the following...

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {

    ByteBuf delimiter;
    byte[] ETX = {0x03};
    byte[] STX = {0x02};

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        setupDelimiter();
        ch.pipeline().addLast(new MyDecoder(65*1024, false, delimiter));
        ch.pipeline().addLast(new ByteArrayDecoder());
        ch.pipeline().addLast(new ByteArrayEncoder());
        ch.pipeline().addLast(new MyHandler());
   }

   private void setupDelimiter(){
       delimiter = Unpooled.copiedBuffer(ETX);

   }

}

一切正常,我得到了完整的消息,包括LRC,它是ETX之后的1个字节,但是它引发以下异常....

Everything works as expected, I get my full message including the LRC which is the 1 byte after the ETX, however it throws the following Exception....

May 09, 2014 5:11:43 PM io.netty.channel.DefaultChannelPipeline$TailHandler exceptionCaught
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It
usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: java.lang.NullPointerException
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:258)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:140)
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:74)
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:138)
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:320)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:794)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at com.test.MyDecoder.decode(MyDecoder.java:33)
at     io.netty.handler.codec.DelimiterBasedFrameDecoder.decode(DelimiterBasedFrameDecoder.java:216)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:227)
... 11 more

我不确定为什么会这样...

I am not sure why this is happening...

对我应该看的东西有什么想法吗?

Any thoughts on what I should be looking at?

谢谢 蒂姆

推荐答案

您将需要自己的DelimiterBasedFrameDecoder版本来处理这种情况.基本上只是Netty随附的副本的一个副本,但在定界符之后又消耗了1个字节.

You will need your own version of a DelimiterBasedFrameDecoder that handles the case. Basically just a copy of the one shipped with Netty but also consume 1 more byte after the delimiter.

这篇关于Netty自定义DelimiterBasedFrameDecoder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆