1
votes

I am making Netty Server that satisfies the following conditions:

  1. Server needs to do transaction process A, when it receives packet from its client.
  2. After finishing transaction, if it is still connected, it sends back return message to client. If not, do some rollback process B.

But my problem is that when I send back to client, the Server does not know wheter it is still connected or not.

I've tried following codes to figure out its connection before sending messages. However it always succeeds even though client already closed its socket. It only fails when client process is forcibly killed (e.g. Ctrl+C)

    final ChannelFuture cf = inboundChannel.writeAndFlush(resCodec);

    cf.addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) {

            if (future.isSuccess()) {
                inboundChannel.close();

            } else {
                try {
                // do Rollback Process B Here
            }
        }
    });

I thought this is because of TCP protocol. If client disconnect gracefully, then FIN signal is sent to server. So it does think writeAndFlush succeeds somehow even when it doesn't.

So I've tried following code too, but these have the same result (always return true)

    if(inboundChannel.isActive()){
      inboundChannel.writeAndFlush(msg);
    } else{
      // do RollBack B
    }

    // Similar codes using inboundChannel.isOpen(), inboundChannel.isWritable()

Neither 'channelInactive' event nor 'Connection Reset by Peer' exception occur in my case.




This is the part of Netty test client code that I used.

    public void channelActive(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(message).addListener(ChannelFutureListener.CLOSE);        
    }


How can I notice disconnection at the time that I want to reply?

1
This is the same problem that can happen in the SMTP protocol, a mail server has received the mail, but the client never knows it. One of the ways this can be solved is using client side generated transaction numbers, and when the client "reconnect", ask for the state about that transaction id - Ferrybig
You should not attempt a rollback even if you do detect a disconnected client. He told you to perform the transaction, you performed it: you can't confirm it to him, but that's is problem, not yours. The solution to that is to design your transactions so that they are idempotent, i.e. that reapplying an already applied transaction does nothing. - user207421

1 Answers

0
votes

May be you should override the below method and see if the control goes here when channel is closed.

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    // write cleanup code
}

I don't think its possible to track that whether client is connected or not in netty because there is an abstraction between netty and client.