Netty handler not called

I am trying to log into Netty using a simple client-server application (see code below).

I am struggling with two problems:

  • ConfigServerHandler respectively. ConfigClientHandler is called correctly. But FeedbackServerHandler accordingly. FeedbackClientHandler is never called. What for? According to the documentation, handlers should be called one after another.

  • I would like to have several handlers. Each of these handlers is only interested in certain messages that are sent by the other party (for example, sending by the client received by the server).

    • Should I filter messages after they have been received by the handler (channelRead)? How can I distinguish between different lines? Separating objects, this should be fairly easy, taking them apart.
    • Can I define different ChannelPipelines for a SocketChannel?
    • further approaches?

Thanks for your help!

Kj

Here's how to create a server:

public void run() throws Exception { 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 ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new ConfigServerHandler(), new FeedbackServerHandler()); } }); b.bind(mPort).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } 

One of the Handler classes (FeedbackServerHandler does the same, but parses in Integer):

 public class ConfigServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("ConfigServerHandler::channelRead, " +(String)msg); ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } 

The client side looks pretty similar:

 public Client(String host, int port) throws InterruptedException { EventLoopGroup workerGroup = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(workerGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new ConfigClientHandler(), new FeedbackClientHandler()); } }); b.connect(host, port).sync().channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } 

And here is one of the client-side handlers (the other sends an Integer message and parses into Integer in the channelRead method):

 public class ConfigClientHandler extends ChannelInboundHandlerAdapter { private final String firstMessage = "blubber"; @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("ConfigClientHandler::channelActive"); ctx.writeAndFlush(firstMessage); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("ConfigClientHandler::channelRead, " +(String)msg); ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } 

}

+5
source share
1 answer

You use the ChannelInboundHandlerAdapter , which is good for your "middle" ConfigXxxxxHandler handler.

But you use the channelRead method, and then use inside ctx.write(msg) . ctx.write(msg) will first write msg back to another server through the previous handler ( ObjectDecoder ), and not to the next handler ( FeedbackClientHandler in your case).

You should use the following if you want to send a message to the following handler:

 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { System.out.println("ConfigClientHandler::channelRead, " +(String)msg); ctx.fireChannelRead(msg); } 

And, of course, there is no ctx.flush() in channelReadComplete (as it is no longer written there). But in your final FeedbackClientHandler , of course, use the flush method with ctx.write(yourNewMessage) or use ctx.writeAndFlush(yourNewMessage) .

So, to resume:

  • ctx.write will send a message to the wire, so the channel will be transmitted to the previous handler, and then to the network, so the Outgoing method
  • ctx.fireChannelRead will send a message to the next next handler (vice versa), so the Inbound method

See http://netty.io/wiki/new-and-noteworthy-in-4.0.html#wiki-h4-16 for more details.

Perhaps you can also invert Encoder / Decoder, since it is generally recommended to have a decoder first and then an encoder in the pipeline.

  p.addLast( new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new ObjectEncoder(), new ConfigClientHandler(), new FeedbackClientHandler()); 
+5
source

Source: https://habr.com/ru/post/1207375/


All Articles