【问题标题】:Netty Encoder Not Being Called未调用 Netty 编码器
【发布时间】:2023-03-18 19:34:01
【问题描述】:

使用 Netty 4.0.27 和 Java 1.8.0_20

所以我试图通过构建一个简单的聊天服务器来了解 Netty 的工作原理(我猜是典型的网络教程程序?)。设计我自己的简单协议,称为 ARC(Andrew's Relay Chat)......这就是为什么你在代码中经常看到 ARC。 K,所以这就是问题所在。

所以我在这里启动服务器并注册各种处理程序...

    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();
        }
    }

我的“inboundHandler”确实在用户连接时被调用。

@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);
}

这是我的编码器,似乎根本没有被调用...

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;
    }
}

所以,

调用ctx.writeAndFlush(packet)的代码;已运行,但似乎在任何时候都没有调用编码器。我错过了一些明显的东西吗?也许我错误地添加了编码器?虽然当我将它与我见过的其他示例进行比较时,它看起来是正确的。

感谢您的帮助。

【问题讨论】:

    标签: java netty encoder


    【解决方案1】:

    您的编码器 (ArcEncoder) 放置在您的入站处理程序之后。这意味着,ctx.*() 方法调用永远不会被编码器评估。要解决您的问题,您必须将 ArcEncoder 移到入站处理程序之前:

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

    更多活动评估顺序请阅读the API documentation of ChannelPipeline

    【讨论】:

    • 好的,谢谢。似乎没有用,但我会看看那个页面。
    • 好的,开始工作了。这部分页面是最有用的:“在给定的示例配置中,当事件入站时,处理程序评估顺序为 1、2、3、4、5。当事件出站时,顺序为 5、4, 3、2、1。“谢谢!
    【解决方案2】:

    我认为问题在于您正在使用 ChannelHandlerContext 写入 Channel。这样做是将消息插入到处理程序点的管道中,出站。但是由于您的解码器是在管道中的编码器之前添加的,这意味着您使用解码器上下文编写的任何内容都将插入到管道中的编码器之后

    确保编码器被调用的正确方法是调用:

    ctx.channel.writeAndFlush()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-19
      • 2023-03-25
      • 2014-02-15
      • 1970-01-01
      相关资源
      最近更新 更多