2017-09-22 23 views
2

最近、私のプロジェクトでnettyを使用し始めました。私は、Nettyがどのように動作するかを理解するために、HexDumpProxyの例を実装しました。私はStringDecoderとStringEncoderをチャネルパイプラインに追加してパイプラインが壊れてしまうという問題に直面しています。デコーダ/エンコーダが存在しない場合、プログラムは正常に機能します。誰かが私に説明することができますなぜこれが起こるのですか?どんな助けも高く評価されます!デコーダ/エンコーダを追加するとNettyパイプラインが壊れる

次のコードを追加しています。

メインクラス:

public final class HexDumpProxy { 

public static void main(String[] args) throws Exception { 

    // Configure the bootstrap. 
    EventLoopGroup bossGroup = new NioEventLoopGroup(1); 
    EventLoopGroup workerGroup = new NioEventLoopGroup(); 
    try { 
     ServerBootstrap b = new ServerBootstrap(); 
     b.group(bossGroup, workerGroup) 
     .channel(NioServerSocketChannel.class) 
     .handler(new LoggingHandler(LogLevel.INFO)) 
     .childHandler(new HexDumpProxyInitializer("127.0.0.1", 9000)) 
     .childOption(ChannelOption.AUTO_READ, false) 
     .bind(8000).sync().channel().closeFuture().sync(); 
    } finally { 
     bossGroup.shutdownGracefully(); 
     workerGroup.shutdownGracefully(); 
     } 
    } 
} 

イニシャライザクラス:

public class HexDumpProxyInitializer extends ChannelInitializer<SocketChannel> { 

private final String remoteHost; 
private final int remotePort; 

public HexDumpProxyInitializer (String remoteHost, int remotePort) { 
    this.remoteHost = remoteHost; 
    this.remotePort = remotePort; 
} 

@Override 
protected void initChannel(SocketChannel ch) throws Exception { 
    ch.pipeline().addLast("frameDecoder", new LineBasedFrameDecoder(80)); 
    ch.pipeline().addLast("decoder", new StringDecoder()); 
    ch.pipeline().addLast("encoder", new StringEncoder()); 
    //ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO)); 
    ch.pipeline().addLast(new HexDumpProxyFrontendHandler(remoteHost, remotePort)); 
    } 

} 

フロントエンドHandlerクラス:

public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter { 

private final String remoteHost; 
private final int remotePort; 

private Channel serverChannel; 

public HexDumpProxyFrontendHandler(String remoteHost, int remotePort) { 
    this.remoteHost = remoteHost; 
    this.remotePort = remotePort; 
} 

@Override 
public void channelActive(ChannelHandlerContext ctx) { 
    final Channel clientChannel = ctx.channel(); 

    Bootstrap b = new Bootstrap(); 
    b.group(clientChannel.eventLoop()) 
    .channel(ctx.channel().getClass()) 
    .handler(new HexDumpProxyBackendHandler(clientChannel)) 
    .option(ChannelOption.AUTO_READ, false); 

    ChannelFuture f = b.connect(remoteHost, remotePort); 
    serverChannel = f.channel(); 
    f.addListener(new ChannelFutureListener() { 
     public void operationComplete(ChannelFuture future) { 
      if (future.isSuccess()) { 
       clientChannel.read(); 
      } 
      else 
       clientChannel.close(); 
      } 

     }); 
} 

@Override 
public void channelRead (final ChannelHandlerContext ctx, Object msg) { 
    if (serverChannel.isActive()) { 
     System.out.println("************" + msg); 
     serverChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() { 
      public void operationComplete(ChannelFuture future) { 
       if (future.isSuccess()) { 
        ctx.channel().read(); 
        System.out.println("Read from server channel. - channelRead"); 
       } else { 
        future.channel().close(); 
        System.out.println("Close server channel."); 
       } 
      } 
     }); 
    } 
} 

@Override 
public void channelInactive (ChannelHandlerContext ctx) { 
    if (serverChannel != null) { 
     closeOnFlush(serverChannel); 
     System.out.println("close on flush - server channel"); 
    } 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
    cause.printStackTrace(); 
    ctx.close(); 
} 

static void closeOnFlush (Channel ch) { 
    if (ch.isActive()) 
     ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); 
} 

@Override 
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
    ctx.flush(); 
    ctx.channel().read(); 
    } 
} 

バックエンドHandlerクラス:

public class HexDumpProxyBackendHandler extends ChannelInboundHandlerAdapter { 

private final Channel clientChannel; 

public HexDumpProxyBackendHandler (Channel clientChannel) { 
    this.clientChannel = clientChannel; 
} 

@Override 
public void channelActive (ChannelHandlerContext ctx) { 
    ctx.channel().read(); 
    System.out.println("Read from client channel. - channelActive"); 
} 

@Override 
public void channelRead (final ChannelHandlerContext ctx, Object msg) { 
    System.out.println("~~~~~~~~~~~" + msg); 
    clientChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() { 
     public void operationComplete(ChannelFuture future) { 
      if (future.isSuccess()) { 
       clientChannel.read(); 
       System.out.println("Read from client channel. - channelRead"); 
      } else { 
       clientChannel.close(); 
       System.out.println("Close client channel."); 
       } 
      } 
     }); 
} 

@Override 
public void channelInactive (ChannelHandlerContext ctx) { 
    HexDumpProxyFrontendHandler.closeOnFlush(clientChannel); 
    System.out.println("close on flush - client channel"); 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
    cause.printStackTrace(); 
    ctx.close(); 
} 

@Override 
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
    ctx.flush(); 
    ctx.channel().read(); 
    } 
} 

答えて

0

今後同様の問題に直面するすべての人にとって、問題がどこにあるのかを発見しました。

クラスHexDumpProxyFrontendHandlerでは、新しいHexDumpProxyBackendHandler(clientChannel)をブートストラップ中にハンドラとして使用する代わりに、新しいクラスを作成します。 HexDumpProxyBackendInitializer(clientChannel)でクラスと同じ方法でパイプラインを初期化します。クラスHexDumpProxyInitializer

これは誰かを助けることができますように!

関連する問題