1

I want to control bandwidth for data transfer. According to Netty document, they suggest:

In your handler, you should consider to use the channel.isWritable() and channelWritabilityChanged(ctx) to handle writability, or through future.addListener(new GenericFutureListener()) on the future returned by ctx.write().

Here is my channel initializer source code:

public class MyChannelInitializer extends ChannelInitializer<Channel>
        {
            private int mode;
            private Server server;
            private String fileName;
            public MyChannelInitializer(Server server, int mode,String fileName)
            {
                this.mode=mode;
                this.server=server;
                this.fileName=fileName;
            }
            @Override
            protected void initChannel(Channel ch) throws Exception 
            {
                if (this.mode==MyFtpServer.RECEIVEFILE)
                {
                    ch.pipeline().addLast(new ChannelTrafficShapingHandler(0L,10240L));  
                    ch.pipeline().addLast(new ReceiveFileHandler(this.fileName,server));
                }
                else
                {
                    ch.pipeline().addLast(new ChannelTrafficShapingHandler(10240L,0L));
                    ch.pipeline().addLast("streamer", new ChunkedWriteHandler()); 
                    ch.pipeline().addLast("handler",new SendFileHandler(this.fileName,server));
                }
            }   
        }

Here is Send File Handler source code:

    public class SendFileHandler extends SimpleChannelInboundHandler<ByteBuf> 
    {
        String fileName;
        PassiveServer txServer=null;
        public SendFileHandler(String fileName, PassiveServer txServer)
        {
            this.fileName=fileName;
            this.txServer=txServer;
        }
        public void channelWritabilityChanged(ChannelHandlerContext ctx)throws IOException
        {
            System.out.println("isWritable="+ctx.channel().isWritable());
        }
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws IOException 
        {
            System.out.println("SendFileHandler active");
        }
    }   

Would you tell me why "channelWritabilityChanged" method in my SendFileHandler is never trigger, only channelActive method is triggered.?

After I changed SendFileHandler.channelActive method as the following:

public void channelActive(ChannelHandlerContext ctx) throws IOException 
{
    Calendar  startTime;
    System.out.println("SendFileHandler active");
    startTime=Calendar.getInstance();
    ctx.fireChannelWritabilityChanged();
}   

The SendFileHandler.channelWritabilityChanged method still not triggered. Would anyone tell me why?

The KNVB
  • 3,588
  • 3
  • 29
  • 54

1 Answers1

0

I believe because ChunkedWriteHandler does the job, taking into account writability directly. However, since its last code in channelWritabilityChanged is:

ctx.fireChannelWritabilityChanged();

You should have the signal of writability changed.

But do you send any file? Because in your code, not, and therefore no channelWritabilityChanged shall be raized since there seems to be no write at all... (of course, writability only occurs on write part, not on read part).

You could also have a look at this thread regarding traffic shaping.

Community
  • 1
  • 1
Frederic Brégier
  • 2,108
  • 1
  • 18
  • 25
  • Yes, I want to send file, here is my original code: – The KNVB Dec 21 '15 at 01:59
  • Yes, I want to send file, here is my original SendFileHandler channelActive: public void channelActive(ChannelHandlerContext ctx) throws IOException { Calendar startTime; System.out.println("SendFileHandler active"); startTime=Calendar.getInstance(); ChannelFuture f = ctx.writeAndFlush(new ChunkedFile(new File(this.fileName))); f.addListener(new FileTransferCompleteListener(txServer,startTime)); } However, I found that ctx.channel().isWritable() in channelWritabilityChanged method alway return false. – The KNVB Dec 21 '15 at 02:16
  • Although, the file transfer completed succesfully, I don't know why ctx.channel().isWritable() alway return false . Besides that, I have download the discard server and client from the following URL: https://github.com/fredericBregier/netty/tree/8f704e6020de364b031a77e1ee403d3ae4d8e10d/example/src/main/java/io/netty/example/discard Would you tell me how can I make it works? I am using Netty version 4.0.33, Eclipse Luna and Windows 8.1. thank you very much – The KNVB Dec 21 '15 at 02:17
  • The discard client and server example is inspired from the one you can find in Netty directly. I proposed several months ago a change to take into account the traffic shaping example. You have to launch the server, then the client. You can start from the Netty native version and then apply the changes from my example. – Frederic Brégier Dec 21 '15 at 09:33
  • So you get the writability changed when you write the file to out. As you put in the middle the `ChunkedWriteHandler` (which is good), probably when you get the writability changed information, this handler is already in its way to send new chunk, so the writability gets back to false immediately. Did you get a traffic shaping from client perspective ? – Frederic Brégier Dec 21 '15 at 09:36
  • I add ChannelTrafficShapingHandler to pipeline only. What do you mean " traffic shaping from client perspective"? – The KNVB Dec 22 '15 at 05:31
  • I mean: once you send the file, did you see any traffic shaping (bandwidth limitation) during the transfer from the server to the client? You may not see anything from server perspective (since `ChunkedWriteHandler` and `ChannelTrafficShapingHandler` shall take care of this), except the time spent as seen on the client side. – Frederic Brégier Dec 22 '15 at 08:37
  • The file transmission time in sending and receiving end are also affected. However, the channelWritabilityChanged method still is not triggered, even I replace "ctx.writeAndFlush" with ctx.fireChannelWritabilityChanged(). Do you mean in order to trigger channelWritabilityChanged method, I need to write something to channel first? thank you very much – The KNVB Dec 22 '15 at 09:35
  • The channel writability changes when something occurs. If you do not send anything, it does not changed (by default, the channel is writable). But as you write immediately (in channelActive, which is 1 of the ways), the `ChunkedFile` with `ChunkedWriteHandler` take themselves the file sending by chunk, without any more action from your handler. As there is the `ChannelTrafficShapingHandler` in the pipeline, the writability is taken into account directly by both sides (`ChunkedWriteHandler` as a writer using the writability status, `ChannelTrafficShapingHandler` as manager of bandwidth). – Frederic Brégier Dec 22 '15 at 13:31
  • Currently, I am setting both WRITE_BUFFER_LOW_WATER_MARK and WRITE_BUFFER_HIGH_WATER_MARK to 1 to make the event is triggered. – The KNVB Feb 17 '16 at 09:34
  • If you did use both `ChunkedWriteHandler` and `ChannelTrafficShapingHandler` to write a `ChunkedFile`, your handler will have no chance to see any writability change event, since they manage this for you (traffic will generate events that will be catch by writeHandler directly, therefore not getting to your handler which is next in the pipeline).. – Frederic Brégier Feb 17 '16 at 19:18