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