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 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程