Hi,

I am just writing some test applications using Netty so I can make sure I 
understand the fundamentals before I start working on putting it into a 
production environment and Im having a few issues with closing the 
connection to the client from the server.  

Here is what i have so far :-

I wire up the server using the following :-

                EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("decoder", new 
LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE, 0, 2, 
0, 2, true) );
ch.pipeline().addLast(new 
ObjectDecoder(ClassResolvers.cacheDisabled(null)));
ch.pipeline().addLast("length", new LengthFieldPrepender(2));
ch.pipeline().addLast(new ObjectEncoder());
ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(10, 10, 0));
ch.pipeline().addLast(new MessageHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true); //Have tried without this 
as well
//Bind And Start To Accept Incoming Connections
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}

My server message handler is as follows :-

public class MessageHandler extends ChannelDuplexHandler {

@Override
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) 
throws Exception {
// TODO Auto-generated method stub
//super.disconnect(ctx, promise);
System.out.println("Client Reader From " + ctx.channel().remoteAddress() + 
" has disconnected");
}

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) 
throws Exception {
if ( evt instanceof IdleStateEvent ) {
IdleStateEvent e = (IdleStateEvent)evt;
if ( e.state() == IdleState.READER_IDLE ) {
System.out.println("Client Reader From " + ctx.channel().remoteAddress() + 
" is idle ");
//Close The Connection - Trying a few different things to try and force the 
disconnect and see what happens
ctx.channel().close();
ctx.channel().deregister();
ctx.channel().disconnect();
} 
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
}

private static final ChannelGroup channels = new DefaultChannelGroup( 
GlobalEventExecutor.INSTANCE);

@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
//super.channelRegistered(ctx);
//System.out.println("New Client Has Connected From " + 
ctx.channel().remoteAddress() );
System.out.println("Client From " + ctx.channel().remoteAddress() + " is 
Registered");
}

@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception 
{
// TODO Auto-generated method stub
//super.channelUnregistered(ctx);
System.out.println("Client From " + ctx.channel().remoteAddress() + " has 
Deregistered");
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
//super.channelActive(ctx);
System.out.println("New Client Has Connected From " + 
ctx.channel().remoteAddress() );
channels.add(ctx.channel());
System.out.println("There are currently " + channels.size() + " Channels 
Connected");
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
//super.channelInactive(ctx);
System.out.println("Client From " + ctx.channel().remoteAddress() + " is 
Inactive");
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws 
Exception {
// TODO Auto-generated method stub
//super.channelRead(ctx, msg);
BaseMessage m = (BaseMessage)msg;
System.out.println("'" + channels.size() + "'" + " Received Mesage From " + 
ctx.channel().remoteAddress() + " " + m.toString());
}

}

Then on the client side, I have the following :-

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 ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {

ch.pipeline().addLast("decoder", new 
LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN,
Integer.MAX_VALUE, 0, 2, 0, 2, true));
ch.pipeline().addLast(new 
ObjectDecoder(ClassResolvers.cacheDisabled(null)));
ch.pipeline().addLast("length", new LengthFieldPrepender(2));
ch.pipeline().addLast(new ObjectEncoder());

ch.pipeline().addLast(new ClientHandler());

}

});

// Start The Client
                        //I added the Listeners just to see what happened 
and when they were called
                        //First try didnt have any of these listeners
                      
ChannelFuture f = b.connect(this.ServerAddress, this.ServerPort).sync();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture arg0) throws Exception {
if (arg0.isSuccess()) {
System.out.println("Client Has Connected");
addCloseListener(arg0.channel());
}
}
private void addCloseListener( Channel channel ) {
channel.closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture arg0) throws Exception {
System.out.println("Client Connection Lost ");
arg0.channel().close();
arg0.channel().deregister();
arg0.channel().disconnect();
}
});
}
});

// Wait Until The Connection Is Closed
f.channel().closeFuture().sync();
System.out.println("Client Is After Sync");

} catch ( Exception exc ) {
exc.printStackTrace();
} finally {

workerGroup.shutdownGracefully();
System.out.println("Worker Group Shut Down Gracefully");

}
System.out.println("Client Is After Sync");

Then my client handler is as follows :-

public class ClientHandler extends ChannelInboundHandlerAdapter {

@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
//super.channelRegistered(ctx);
System.out.println("Client Channel is Registered");
}

@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception 
{
// TODO Auto-generated method stub
//super.channelUnregistered(ctx);
System.out.println("Client Channel is Unregistered");
}

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
System.out.println("Client Channel is Inactive");

                //Again Just testing here to see what happens..
ctx.channel().close().sync();
ctx.channel().close().syncUninterruptibly();
ctx.channel().closeFuture().sync();
ctx.channel().closeFuture().syncUninterruptibly();
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
BaseMessage testMessage = new BaseMessage( 1, new Date() );
ctx.writeAndFlush( testMessage );
for ( int i=0; i < 10; i++) { 

BaseMessage testMessage = new BaseMessage( 1, new Date() );
ctx.writeAndFlush( testMessage );
                        //Shouldnt really sleep in here but just for 
testing should be ok 
Thread.sleep(1000); 
}
}

}

So essentially, my client connects and then sends through 10 messages and 
then the server will detect the Channel Inactive event and at this point I 
want the server to close the connection to the client.  In a real world 
scenario, I would send a request to see if the client is still online but 
so I understand how it all goes together i thought I would try to force the 
disconnect at this stage.  

What is currently happening is as follows :-

Server detects that the client is connected and prints out the 10 messages 
that are sent

Client From /127.0.0.1:22880 is Registered
New Client Has Connected From /127.0.0.1:22880
There are currently 1 Channels Connected
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:09 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:10 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:11 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:12 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:13 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:14 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:15 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:16 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:17 AEDT 2017
'1' Received Mesage From /127.0.0.1:22880 Message Type 1 - Sun Feb 26 
16:44:18 AEDT 2017


The server then detects that the Client Reader is Idle
The server then detects that the Client Reader has Deregistered

The client then reconnects for some reason (this is the bit I am struggling 
with)

Sun Feb 26 17:02:16 AEDT 2017 Client Reader From /127.0.0.1:24495 is idle 
Sun Feb 26 17:02:16 AEDT 2017 Client From /127.0.0.1:24495 is Inactive
Sun Feb 26 17:02:16 AEDT 2017 Client From /127.0.0.1:24495 has Deregistered
Sun Feb 26 17:02:16 AEDT 2017 Client From /127.0.0.1:24549 is Registered
Sun Feb 26 17:02:16 AEDT 2017 New Client Has Connected From /127.0.0.1:24549
Sun Feb 26 17:02:16 AEDT 2017 There are currently 1 Channels Connected

The client then sends 10 more messages and then terminates

Sun Feb 26 17:01:57 AEDT 2017 Client Channel is Registered
Sun Feb 26 17:02:07 AEDT 2017 Client Has Connected
Sun Feb 26 17:02:16 AEDT 2017 Client Connection Lost 
Sun Feb 26 17:02:16 AEDT 2017Client Is After First Sync
Sun Feb 26 17:02:16 AEDT 2017 Client Channel is Unregistered
Sun Feb 26 17:02:16 AEDT 2017 Worker Group Shut Down Gracefully
Sun Feb 26 17:02:16 AEDT 2017 Client Is After Finally
Sun Feb 26 17:02:16 AEDT 2017 Client Channel is Registered
Sun Feb 26 17:02:26 AEDT 2017 Client Has Connected
Sun Feb 26 17:02:35 AEDT 2017 Client Connection Lost 

I must be missing something in the fundamental concepts as I thought the 
calling ctx.channel().close(); in the server would force the client to 
disconnect.

In a real world example, this reconnect is probably a good thing but I am 
just trying to understand why it is happening.

Any assistance would be greatly appreciated.

Thanks,

Deacon.

-- 
You received this message because you are subscribed to the Google Groups 
"Netty discussions" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/netty/9580d249-9e86-4491-8e4b-48fdc7a210c9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to