Cheo Cheng
Cheo Cheng

Reputation: 15

Blocking tcp packet receiving in Netty 4.x

How can I block netty to send ACK responese to client in netty 4.x ?

I'm trying to control TCP packet receive speed in netty in order to forward these packet to another server . Netty receive all client packets immediately ,but netty need more time send them out , so client think it finished after sending to netty .

So , I want to know how to block received packets when netty forwarding packets which are received before to another server .

Upvotes: 0

Views: 977

Answers (1)

Frederic Brégier
Frederic Brégier

Reputation: 2206

Not sure to really understand your question. So I try to reformulate:

  • I suppose that your Netty server is acting as a Proxy between clients and another server.
  • I suppose that what you want to do is to send the ack back to the client only once you really send the forwarded packet to the final server (not necesseraly received by the final server, but at least send by Netty proxy).

If so, then you should use the future of the forwarded packet to respond back with the ack, such as (pseudo code):

channelOrCtxToFinalServer.writeAndFlush(packetToForward).addListener(new ChannelFutureListener() {
  public void operationComplete(ChannelFuture future) {
    // Perform Ack write back
    ctxOfClientChannel.writeAndFlush(AckPacket);
  }
});

where:

  • channelOrCtxToFinalServer is one of ChannelHandlerContext or Channel connected to your remote final server from your Netty proxy,
  • and ctxOfClientChannel is the current ChannelHandlerContext from your Netty handler that receive the packet from the client in public void channelRead(ChannelHandlerContext ctxOfClientChannel, Object packetToForward) method.

EDIT: For the big file transfer issue, you can have a look at the Proxy example here.

In particular, pay attention on the following:

  • Using the same logic, pay attention on receiving data one by one from client:

    yourServerBootstrap..childOption(ChannelOption.AUTO_READ, false);
    // Allow to control one by one the speed of reception of client's packets
    
  • In your frontend handler:

    public void channelRead(final ChannelHandlerContext ctx, Object msg) {
        if (outboundChannel.isActive()) {
            outboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) {
                    if (future.isSuccess()) {
                        // was able to flush out data, start to read the next chunk
                        ctx.channel().read();
                    } else {
                        future.channel().close();
                    }
                }
            });
        }
    }
    
  • And finally add, using the very same logic, the final ack to your client (ack depending of course on your protocol): (see here and here)

    /**
     * Closes the specified channel after all queued write requests are flushed.
     */
    static void closeOnFlush(Channel ch) {
        if (ch.isActive()) {
            ch.writeAndFlush(AckPacket).addListener(ChannelFutureListener.CLOSE);
        }
    }
    

Upvotes: 2

Related Questions