I am trying to understand and use Netty in my projects, so started off with the basic DiscardServer Example presnted in Netty's user guide.
The below is almost a copy-paste of the original code...
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap sb = new ServerBootstrap();
sb.group(bossGroup, workerGroup);
sb.channel(NioServerSocketChannel.class);
sb.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
});
// Set some socket options such as socket queue backlog and keepalive.
sb.option(ChannelOption.SO_BACKLOG, 128);
sb.childOption(ChannelOption.SO_KEEPALIVE, true);
// bind to port and start listening.
ChannelFuture f = sb.bind(port).sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
And when I create a main method, as below, it runs fine, but then just gets terminated.
public static void main(String[] args) throws Exception {
int port = Integer.parseInt(args[0]);
System.out.println("Starting discard server...");
new DiscardServer(port).run();
System.out.println("Discard server returning...");
}
The program output is:
Starting discard server... Discard server returning...
And then the program terminates.
I am expecting that the event loop inside the netty classes should make my server, but it doesn't seem to happen that way. Should I write a while loop in my main method to ensure my server keeps running?
UPDATE:
The same program works flawlessly, if I use Netty 4.x series of jar files. I think the version 5 is still evolving, so errors are expected.
You forgot to add the wait on close operation:
What you do right now is starting the server to listen, then finishing your own main after shutdown your executors.
You have to block on something, and the best for the server is to wait on the closeFuture operation.
Then in your handler, you have to decide when to close the server (
f.channel().close()
), which will turn to awake the main procedure and finishing the server.Important notice: you have to distinguish the "child" channel (which you get from
ctx.channel()
in your handler, attached to one unique client connection) and the "parent" channel (which you get fromctx.channel().parent()
). Closing the "child" will not terminate thef.channel()
since this one is the "parent" one (the listener). So you have to do something likectx.channel().parent().close()
.Note that the current example of DiscardServerHandler does not include any code to stop (it is a forever running handler).