asialee029 2013-01-31 19:08
浏览 435
已采纳

netty里面FrameDecoder的理解

[color=blue][size=medium]在netty里面,messageReceived的实现如下:
[/size][/color][code="java"]
Object m = e.getMessage();
if (!(m instanceof ChannelBuffer)) {
ctx.sendUpstream(e);
return;
}

    ChannelBuffer input = (ChannelBuffer) m;
    if (!input.readable()) {
        return;
    }

    ChannelBuffer cumulation = cumulation(ctx);
    if (cumulation.readable()) {
        cumulation.discardReadBytes();
        cumulation.writeBytes(input);
        callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
    } else {
        callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
        if (input.readable()) {
            cumulation.writeBytes(input);
        }
    }

[/code]

[color=blue][size=medium]我们看到比较关键的是cumulation函数,函数如下:
[/size][/color][code="java"]
private ChannelBuffer cumulation(ChannelHandlerContext ctx) {
ChannelBuffer c = cumulation;
if (c == null) {
c = ChannelBuffers.dynamicBuffer(
ctx.getChannel().getConfig().getBufferFactory());
cumulation = c;
}
return c;
}
[/code]
[color=blue][size=medium]在这个里面为什么要这么实现呢,什么时候cumulation不为空呢?
我们再看看上面的实现:[/size][/color]
[code="java"]
if (cumulation.readable()) {
cumulation.discardReadBytes();
cumulation.writeBytes(input);
callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
} else {
callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());
if (input.readable()) {
cumulation.writeBytes(input);
}
}
[/code]
[color=blue][size=medium]这个if和else里面的逻辑应该怎么理解。
[/size][/color]

  • 写回答

2条回答 默认 最新

  • ambitiouswolf 2013-02-04 20:45
    关注

    1、什么时候cumulation不为空呢?
    初次运行,cumulation == null,所以ChannelBuffer cumulation = cumulation(ctx);创建了一个空的dynamicBuffer;

    cumulation.readable()是false,所以执行的是:
    else {

    callDecode(ctx, e.getChannel(), input, e.getRemoteAddress());

    if (input.readable()) {

    cumulation.writeBytes(input);

    }

    }

    callDecode过程中,可能只decode了input的一部分,剩下的字节就写到cumulation,等到下次messageReceived之后,就看到cumulation不为空。(可能messageReceived一次接受了1.5个frame,callDecode只decode了一个frame,剩下的一半写入cumulation)

    2、
    接着上面,这时候cumulation.readable()是true,所以执行的是
    if (cumulation.readable()) {

    cumulation.discardReadBytes();

    cumulation.writeBytes(input);

    callDecode(ctx, e.getChannel(), cumulation, e.getRemoteAddress());
    }

    这里将新接收到的input写入cumulation,然后继续decode。(又接收到了另一半,与先前接收到的合并到一起组成一个完整的frame)

    3、源代码文档上说的很清楚了:
    在像 TCP/IP这种基于流的传输过程中,即使在局域网环境中,报文也可能被分割和重组。FrameDecoder帮助我们将接受到的报文重新整理成有意义的、容易被应用程序逻辑理解的frames。

    In a stream-based transport such as TCP/IP, packets can be fragmented and

    • reassembled during transmission even in a LAN environment. For example,
    • let us assume you have received three packets:
    • +-----+-----+-----+
    • | ABC | DEF | GHI |
    • +-----+-----+-----+
    • because of the packet fragmentation, a server can receive them like the
    • following:
    • +----+-------+---+---+
    • | AB | CDEFG | H | I |
    • +----+-------+---+---+ {@link FrameDecoder} helps you defrag the received packets into one or more
    • meaningful frames that could be easily understood by the
    • application logic. In case of the example above, your {@link FrameDecoder}
    • implementation could defrag the received packets like the following:
    • +-----+-----+-----+
    • | ABC | DEF | GHI |
    • +-----+-----+-----+
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 如何实验stm32主通道和互补通道独立输出
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题