import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import sun.misc.Signal;
import sun.misc.SignalHandler;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class ReusePortServer {
private final int port;
private List<Channel> bindingChannels = new LinkedList<>();
public ReusePortServer(int port) {
this.port = port;
}
private void initSignals() {
Signal.handle(new Signal("BUS"), new SignalHandler() {
@Override public void handle(Signal signal) {
System.out.println("signal arrived");
closeChannels();
}
});
}
synchronized private void closeChannels() {
for (Channel channel : bindingChannels) {
channel.close();
}
bindingChannels.clear();
}
synchronized private void registerChannel(Channel channel) {
bindingChannels.add(channel);
}
public void start() throws Exception {
initSignals();
EventLoopGroup group = new EpollEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(EpollServerSocketChannel.class)
.option(EpollChannelOption.SO_REUSEPORT, true)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>(){
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new ReusePortHandler());
registerChannel(ch);
}
});
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
System.out.println(e.toString());
}
ChannelFuture f = b.bind().sync();
log(String.format("%s started and listen on %s", ReusePortServer.class.getName(), f.channel().localAddress()));
// registerChannel(ch); // ---------------I also tried to register this channel, but after my signaling, it closes my client's connection, rather than keeping it.
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully().sync();
}
}
private final static SimpleDateFormat datefmt = new SimpleDateFormat("HH:mm:ss ");
public static void log(final String msg) {
System.out.print(datefmt.format(new Date()));
System.out.println(msg);
System.out.flush();
}
public static void main(final String[] args) throws Exception {
int port = 12355;
new ReusePortServer(port).start();
}
}
Hi, I am looking a way to stop netty from listening and accepting on server socket, but to finish up any ongoing job on current connections.
I come across the following question: How to stop netty from listening and accepting on server socket
and according to it, I wrote the above code, which receive signal (kill -7
) to do the closing.
But the result is not expected, it closes the tcp connections, and netty can still accept new connection.
Do I use the correct way of stop netty from listening and accepting?
What's wrong here?
You should close the ServerChannel like this:
ChannelFuture f = b.bind().sync();
// Call this once you want to stop accepting new connections.
f.channel().close().sync();
I've spent about two days about this problem. I try this, and it work for me :
First, I declare:
static ChannelFuture future;
Then, when I bind port, I assign future variable:
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerInitializer())
.option(ChannelOption.SO_BACKLOG, NetUtil.SOMAXCONN)
.childOption(ChannelOption.SO_KEEPALIVE, true);
future = b.bind(WS_PORT).sync();
Final, I add a function to handler event when web application stop.
@PreDestroy
void shutdownWorkers() throws InterruptedException {
future.channel().close().sync();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With