2016-03-25 22 views
0

最近Nettyの学習を開始しましたが、今日は問題が発生します。 これは私のサーバコードNettyサーバーはクライアント要求を2回目に受信できません

public class NettyServer2 { 

public static void main(String[] args) { 
    System.out.println("Server start"); 
    new NettyServer2().start(); 
} 

public void start() { 
    EventLoopGroup bossGroup = new NioEventLoopGroup(); 
    EventLoopGroup workerGroup = new NioEventLoopGroup(); 
    ServerBootstrap b = new ServerBootstrap(); 
    ChannelInitializer<SocketChannel> channelInit = new ChannelInitializer<SocketChannel>() { 
     @Override 
     protected void initChannel(SocketChannel ch) throws Exception { 
      ch.pipeline().addLast(new SeverHandler()); 
     } 

    }; 
    b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(channelInit) 
      .option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.SO_KEEPALIVE, true); 
    try { 
     ChannelFuture f = b.bind(8000).sync(); 
     System.out.println("server started on port:8000"); 
     f.channel().closeFuture().sync(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      bossGroup.shutdownGracefully().sync(); 
      workerGroup.shutdownGracefully().sync(); 
     } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
     } 
    } 
} 

}

クラスSeverHandlerがSimpleChannelInboundHandler {

@Override 
protected void messageReceived(ChannelHandlerContext ctx, ByteBuf in) throws Exception { 
    System.out.println("server recevie:" + in.toString(CharsetUtil.UTF_8)); 
    ctx.writeAndFlush(in); 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
    Channel ch = ctx.channel(); 
    if (ch.isActive()) { 
     ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); 
    } 
} 

}

を拡張であり、私のクライアントコードがある

public class NettyClient2 { 

private final String host; 
private final int port; 

public NettyClient2(String host, int port) { 
    this.host = host; 
    this.port = port; 
} 

public void start() throws InterruptedException { 
    EventLoopGroup group = new NioEventLoopGroup(); 
    Bootstrap b = new Bootstrap(); 
    ChannelInitializer<SocketChannel> channel = new ChannelInitializer<SocketChannel>() { 

     @Override 
     protected void initChannel(SocketChannel channel) throws Exception { 
      channel.pipeline().addFirst(new ClientHandler()); 
     } 

    }; 
    b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port)) 
      .handler(new ClientHandler()); 

    try { 
     ChannelFuture f = b.connect().sync(); 
     f.channel().closeFuture().sync(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    }finally{ 
     group.shutdownGracefully().sync(); 
    } 
} 

public static void main(String[] args) throws InterruptedException { 
    new NettyClient2("127.0.0.1", 8000).start(); 
} 

}

クラスClientHandlerのクライアントがクライアントコンソールにI入力が開始されたとサーバが要求を受信しますが、私が要求したときSimpleChannelInboundHandler {

private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); 

@Override 
public void channelActive(ChannelHandlerContext ctx) throws Exception { 
    System.out.println("已经与Server建立连接..."); 
    System.out.println("\n请输入要发送的信息:"); 
    String in = sin.readLine(); 
    ctx.writeAndFlush(Unpooled.copiedBuffer(in,CharsetUtil.UTF_8)); 
} 

@Override 
protected void messageReceived(ChannelHandlerContext ctx, ByteBuf in) throws Exception { 
    System.out.println("client recevie:" + in.toString(CharsetUtil.UTF_8)); 
    System.out.println("已经与Server建立连接..."); 
    System.out.println("\n请输入要发送的信息:"); 
    String read = sin.readLine(); 
    ctx.writeAndFlush(Unpooled.copiedBuffer(read,CharsetUtil.UTF_8)); 
} 

}

を拡張2回目にサーバーがリクエストを受信できない場合は、エラーが表示されます。 enter image description here

+0

私は、サーバー上の例外を見つける:io.netty.util.IllegalReferenceCountExceptionを:REFCNT:0、デクリメント:サーバーに私が使用しているので1 –

+0

OK、私はそれを考えて '(中)ctx.writeAndFlushを;' –

+0

保護のボイドmessageReceived(ChannelHandlerContext ctx、ByteBuf in)は例外をスローします。{ \t \t String inStr = in.toString(CharsetUtil.UTF_8); \t \t System.out.println( "server recevie:" + inStr); \t \t StringBuffer sb = new StringBuffer(inStr); \t \t inStr = sb.reverse()。toString(); \t \t System.out.println( "reverse string:" + inStr); \t \t \t \t ctx.writeAndFlush(Unpooled.copiedBuffer(inStr、CharsetUtil.UTF_8)); –

答えて

0

あなたの問題はSimpleChannelInboundHandlerが自動的にあなたのためのバッファを解放することに起因します。

これに対処するには、送信時にバッファにretain()を呼び出す必要があります。

@Override 
protected void messageReceived(ChannelHandlerContext ctx, ByteBuf in) throws Exception { 
    System.out.println("server recevie:" + in.toString(CharsetUtil.UTF_8)); 
    ctx.writeAndFlush(in.retain()); 
} 
+0

ええ、そうだと思います。しかし、なぜですか?これについての文書はありますか?バージョン4.xIで使用する5.0_alpaha –

+0

SimpleChannelInboundHandlerがバッファを解放しなければならない理由は? –

+0

'SimpleChannelInboundHandler'はフルコードに対してtryyブロックを必要とすることで、コードを単純化するためにハンドラを作成したためバッファを解放します。これをしないChannel InboundHandlerAdaptorもあります – Ferrybig

関連する問題