2015-04-13 2 views
1

Использование Netty 4.0.27 & Java 1.8.0_20Нетти кодировщик не вызывается

Так что я пытаюсь узнать, как Нетти работает путем создания простого сервера чата (типичная программа сети учебник, я думаю?). Проектирование моего собственного простого протокола, называемого 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 (пакетов); запускается, но, похоже, он не вызывает кодер в любой точке. Мне что-то не хватает? Возможно, я неправильно добавляю кодировщик? Хотя это выглядит правильно, когда я сравниваю это с другими примерами, которые я видел.

Спасибо за любую помощь.

ответ

2

Ваш кодировщик (ArcEncoder) размещен после вашего входящего обработчика. Это означает, что вызовы метода ctx.*() никогда не будут оцениваться кодировщиком. Чтобы устранить проблему, вы должны переместить ArcEncoder до въездного обработчика:

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

Для получения дополнительной информации о порядке оценки событий, пожалуйста, прочитайте the API documentation of ChannelPipeline.

+0

Ok спасибо. Кажется, не работает, но я посмотрю на эту страницу. – Anwinity

+0

Хорошо, получилось, что это сработало. Эта часть страницы была наиболее полезной: «В приведенной конфигурации примера порядок обработки обработчиком равен 1, 2, 3, 4, 5, когда событие идет в входящее. Когда событие выходит за пределы, порядок составляет 5, 4, 3, 2, 1. «Спасибо! – Anwinity

1

Я думаю, проблема заключается в том, что вы используете ChannelHandlerContext для записи на канал. Это делается для того, чтобы вставить сообщение в конвейер в точке вашего обработчика, исходя из исходящего. Но поскольку ваш декодер добавлен перед вашим кодировщиком в конвейере, это означает, что все, что вы пишете с использованием контекста декодера, будет вставлено после кодировщика в конвейере.

правильный способ сделать это, чтобы убедиться, что кодер называется это вызов:

ctx.channel.writeAndFlush() 
Смежные вопросы