yu.yicheng
yu.yicheng

Reputation: 11

How to let netty channel.writeAndFlush() throws Exceptions when no TCP ACK response

I am developing an IM server with the Netty4 frame. Meanwhile I used the method named channel.writeAndFlush() to send messages to the client. However, when the socket of the client on the mobile phone shutting down unusually such as turning off the network connections or turning on the airplane mode on the device, the netty4 frame counld not find that the corresponding channel being inactive. Moreover, the ChannelGroupFuture returned by the writeAndFlush() method reports the sending result success with the method ChannelGroupFuture.isSuccess(). So, why the ChannelGroupFuture didn't return me the sending is failed without throwing any exception?

ChannelGroupFuture future = connectionService.sendMessageToUser(msgBase, toUid).sync();

future.addListeners(new ChannelGroupFutureListener(){

@Override
                public void operationComplete(ChannelGroupFuture future)
                        throws Exception {
                    if(future.isDone() && future.isSuccess()){
                        chatMessageService.saveSentChatMessage(msgBase);
                    } else if(!future.isSuccess()){
                        chatMessageService.saveUnsentChatMessage(msgBase);
                    }
});

 public ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher) {
    if (message == null) {
        throw new NullPointerException("message");
    }
    if (matcher == null) {
        throw new NullPointerException("matcher");
    }
    if(matcher instanceof AttributeChannelMatcher){
        Map<Channel, ChannelFuture> futures = new LinkedHashMap<Channel, ChannelFuture>(1);
        AttributeChannelMatcher<T>  attributeMatcher = (AttributeChannelMatcher<T>) matcher;
        Channel c = nonServerChannelMap.get(attributeMatcher.getAttributeKeyValue());

        futures.put(c, c.writeAndFlush(safeDuplicate(message)));
        ReferenceCountUtil.release(message);
        return new DefaultChannelGroupFuture(this, futures, executor);
    }else{
        Map<Channel, ChannelFuture> futures = new LinkedHashMap<Channel, ChannelFuture>(size());

        for (Channel c :  nonServerChannelMap.values()) {
            if (matcher.matches(c)) {
                futures.put(c, c.writeAndFlush(safeDuplicate(message)));
            }
        }
        ReferenceCountUtil.release(message);
        return new DefaultChannelGroupFuture(this, futures, executor);
    }
}

Upvotes: 1

Views: 841

Answers (1)

user207421
user207421

Reputation: 310840

You can't. TCP writes are asynchronous with respect to the application. They don't wait for ACKs before they return. There is a send buffer on the sending side and a receive buffer on the receiving side. All this means that it could take several writes and quite a few seconds before you detect a broken connection.

Upvotes: 3

Related Questions