I need to build a client that initiates a TCP connection with a server and upon response it sends a hand shake request every 10 seconds and gets a response from the server. The server will be able to send another type of request which my client needs to read and act upon. I am using netty 4.0.26.Final.
I have built a client and a dummy server but I am facing an issue which possibly means that there is something I have not understood.
My Client:
String host = "localhost";
int port = 9884;
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new MyChannelPipeline());
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (!line.equals("exit")) {
line = in.readLine();
if (line == null) {
break;
}
}
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
}
The ChannelPipleline:
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline channelPipeline = ch.pipeline();
//Encodes every request send from the client to the server
channelPipeline.addLast("clientRequestEncoder", new ClientRequestEncoder());
//Implements channelActive and exceptionCaught
channelPipeline.addLast("initialRequestHandler", new InitialRequestHandler());
channelPipeline.addLast("byteArrayDecoder", new ByteArrayDecoder());
channelPipeline.addLast("serverResponseDecoder", new ServerResponseDecoder());
channelPipeline.addLast("serverRequestDecoder", new ServerRequestDecoder());
//Reads the responses from the client requests AND
//reads the inbound requests from the server - Implements channelRead
//and exceptionCaught
channelPipeline.addLast("myResponseHandler", new MyResponseHandler());
}
The problem is that when I flush the response to the server (in MyResponseHandler) and exception is caught in InitialRequestHandler:
ERROR=java.lang.UnsupportedOperationException:unsupported message type: ServerResponse (expected: ByteBuf, FileRegion)
I don't see why the response is not flushed back to the server while the hand shake request is always properly flushed. In both write and flush I have used a ChannelFuture
and onOperationComplete this listener f.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
is fired on failure.
Can I use two handlers in the same pipeline or is it bad practise? Moreover how should I fire an unregister event triggered by user input?
I solved this using one Handler that overrides channelActive and channelRead and I rearranged the encoders and decoders properly. I also solved the "unregister event triggered by user input" this way:
String line = "line";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
do {
logger.info("You typed: " + line + ". Please type 'exit' to terminate the program!");
line = in.readLine();
} while (!line.equals("exit"));
logger.info("You typed: " + line + ". Please wait until the application is successfully shutdown...");
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
myChannelPipeline.getMyClientHandler().sendDisconnectRequest(future);
}
});
In sendDisconnectReqeust I send the final request and when I get the final response (in channelRead of MyHandler) I call disconnect on the pipeline:
ChannelPromise cp = new DefaultChannelPromise(ctx.channel());
ctx.channel().pipeline().disconnect(cp);
However I still have other issues with inbound requests that are never received by my client.