简体   繁体   中英

Netty 5 HexDumpProxy issue

I am facing some problem in HexDumpProxy usage. I am using netty lib netty-all-5.0.0.Alpha1.jar.

In HexDumpProxyInitializer class's initChannel method, I am having

@Override
public void initChannel(SocketChannel ch) throws Exception {        
    ChannelPipeline cp = ch.pipeline();        
    cp.addLast(new LoggingHandler(LogLevel.INFO));    
    cp.addLast("decoder", new StringDecoder());
    cp.addLast("encoder", new StringEncoder());        
    cp.addLast(new HexDumpProxyFrontendHandler(remoteHost, remotePort));
}

and in HexDumpProxyFrontendHandler class, I want to process the incoming message as follows, here I am converting Object msg to String and want to change the value, and facing problem in sending modified string.

@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
    String s1 = ((ByteBuf) msg).toString(Charset.defaultCharset());
    if (outboundChannel.isActive()) {
        outboundChannel.writeAndFlush(s1).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    // was able to flush out data, start to read the next
                    // chunk
                    ctx.channel().read();
                    } else {
                    future.channel().close();
                }
            }
        });
    }
}

If I am sending object itself without any modification, its working fine. But if I want to send String , its not throwing any exception, also not working.

After that I have enabled String encoder and decoder in initChannel method, then I am getting the following error,

Proxying *:9999 to 192.168.1.27:8554 ...
java.lang.ClassCastException: java.lang.String cannot be cast to io.netty.buffer.ByteBuf
    at ivz.proxy.HexDumpProxyFrontendHandler.channelRead(HexDumpProxyFrontendHandler.java:68)
    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.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
    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(Unknown Source)

Except the above mentioned methods, I have not changed anything in the code. So, my problem is, I want to change some values in Object msg before sending to server, How can I achive this? Or in other words, is it possible to send String in writeAndFlush method?

I didn't get the logic behind outboundChannel part, but I think there are couple of issues with your code

 cp.addLast(new LoggingHandler(LogLevel.INFO));    
 cp.addLast("decoder", new StringDecoder());
 cp.addLast("encoder", new StringEncoder());        
 cp.addLast(new HexDumpProxyFrontendHandler(remoteHost, remotePort));
  1. Since you have StringDecoder before HexDumpProxyFrontendHandler, so object received in the channelRead will be always String,

    When you write the String object back, it will be encoded to ByteBuff by StringEncoder.

  2. In ChannelFutureListener implementation, no need to call ctx.channel().read()

    Netty will automatically call your handler's channelRead() method

Update :

channel().read() is required if you want to throttle/control the reads, to do that you have set auto read false in channel options, by default auto read is true.

It's quite late, but I also struggled with this.
So here is how I solved it for my case.
In the HexDumpProxyFrontendHandler class I made the following changes to channelActive() :

@Override
public void channelActive(ChannelHandlerContext ctx) {
    final Channel inboundChannel = ctx.channel();
    // Start the connection attempt.
    Bootstrap b = new Bootstrap();
    b.group(inboundChannel.eventLoop()).channel(ctx.channel().getClass())
            .handler(new HexDumpProxyBackendHandler(inboundChannel))
            .option(ChannelOption.AUTO_READ, false);
    ChannelFuture f = b.connect(remoteHost, remotePort);
    outboundChannel = f.channel();
    outboundChannel.pipeline().addFirst(new StringDecoder());  // this 2 lines
    outboundChannel.pipeline().addFirst(new StringEncoder());
    f.addListener(new ChannelFutureListener() {

        public void operationComplete(ChannelFuture future) {
            if (future.isSuccess()) {
                // connection complete start to read first data
                inboundChannel.read();
            } else {
                // Close the connection if the connection attempt has
                // failed.
                inboundChannel.close();
            }
        }
    });
}

So after that, in the channelRead callbacks (for HexDumpProxyFrontendHandler and HexDumpProxyBackendHandler), the messages will be String

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM