Posted at

NettyでFINとRSTを動的に切り替える方法

Nettyを使ってサーバを構築する際に、Channel(ソケット)をcloseする際に状況によってFINとRSTを使い分けたい場合があります。例えば、正常時はFIN(遅延タイムアウト時はRST)だけど、異常を検知した際は直ちにRSTにするような要件がある場合です。


close時のデフォルト動作の指定

Channelをcloseした際のFIN/RSTのどちらを使用するかは、ServerBootstrapを構築する際に指定することができます。

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

EventLoopGroup workerGroup = new NioEventLoopGroup(0);
ServerBootstrap bootstrap = new ServerBootstrap()
.option(ChannelOption.SO_BACKLOG, 1024)
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childOption(ChannelOption.SO_LINGER, 10) // FIN → 遅延タイムアウト(10秒) → RSTでcloseするための指定
.childHandler(new MyChannelInitializer());
// ...


NOTE:

-1を指定するRSTによる解放は無効化されます。



close時にFIN/RSTを選択

ServerBootstrap構築時に指定したデフォルト動作と異なる方法でcloseしたい場合は、ChannelからChannelConfigを取得してSO_LINGERの設定値を変更することで実現することができます。

@ChannelHandler.Sharable

class MyHandler extends SimpleChannelInboundHandler<byte[]> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, byte[] msg) {
// ...
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.channel().config().setOption(ChannelOption.SO_LINGER, 0); // 直ちにRSTでcloseするように指定
ctx.close();
}

}