简体   繁体   中英

Netty Encoder Not Being Called

Using Netty 4.0.27 & Java 1.8.0_20

So I am attempting to learn how Netty works by building a simple chat server (the typical networking tutorial program, I guess?). Designing my own simple protocol, called ARC (Andrew's Relay Chat)... so that's why you see ARC in the code a lot. K, so here's the issue.

So here I start the server and register the various handlers...

    public void start()
    {
        System.out.println("Registering handlers...");
        ArcServerInboundHandler inboundHandler = new ArcServerInboundHandler(this);

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try
        {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
            {
                @Override
                public void initChannel(SocketChannel ch) throws Exception
                {
                    ch.pipeline().addLast(new ArcDecoder(), inboundHandler);
                    ch.pipeline().addLast(new ArcEncoder());
                }
            }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);

            try
            {
                System.out.println("Starting Arc Server on port " + port);
                ChannelFuture f = bootstrap.bind(port).sync();
                f.channel().closeFuture().sync();
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        finally
        {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

My "inboundHandler" does get called when the user connects.

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
    System.out.println("CLIENT CONNECTED"); // THIS PRINTS, REACHES THIS POINT
    ArcPacket packet = new ArcPacket();
    packet.setArc("PUBLIC_KEY");
    packet.setField("KEY", Crypto.bytesToHex(server.getRsaKeys().getPublic().getEncoded()));
    ctx.writeAndFlush(packet);
}

This is my encoder, which does not seem to get called at all...

public class ArcEncoder extends MessageToByteEncoder<ArcPacket>
{
    @Override
    protected void encode(ChannelHandlerContext ctx, ArcPacket msg, ByteBuf out) throws Exception
    {
        System.out.println("ENCODE"); // NEVER GETS HERE
        String message = ArcPacketFactory.encode(msg);
        byte[] data = message.getBytes("UTF-8");
        out.writeBytes(data);
        System.out.println("WROTE");
    }

    @Override
    public boolean acceptOutboundMessage(Object msg) throws Exception
    {
        System.out.println("ACCEPT OUTBOUND MESSAGE"); // NEVER GETS HERE
        return msg instanceof ArcPacket;
    }
}

So,

The code that calls ctx.writeAndFlush(packet); is run, but it doesn't seem to invoke the encoder at any point. Am I missing something obvious? Perhaps I'm adding the encoder incorrectly? Though it looks right when I compare it to other examples I've seen.

Thanks for any help.

Your encoder ( ArcEncoder ) is placed after your inbound handler. It means, the ctx.*() method calls will never be evaluated by the encoder. To fix your problem, you have to move the ArcEncoder before the inbound handler:

ch.pipeline().addLast(new ArcDecoder(), new ArcEncoder(), inboundHandler);

For more information about the event evaluation order, please read the API documentation of ChannelPipeline .

I think the problem is that you're using the ChannelHandlerContext to write to the Channel. What this does is to insert the message in the pipeline at the point of your handler, going outbound. But since your decoder is added before your encoder in the pipeline this means that anything you write using the decoder context will be inserted after the encoder in the pipeline.

The correct way to do it to ensure that the encoder is called is to call:

ctx.channel.writeAndFlush()

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