我们需要区分不同帧的首尾,通常需要在结尾设定特定分隔符或者在首部添加长度字段,分别称为分隔符协议和基于长度的协议,本节讲解 Netty 如何解码这些协议。

一、分隔符协议

  Netty 附带的解码器可以很容易的提取一些序列分隔:

  

  下面显示了使用 “\r\n”分隔符的处理:

  

  下面为 LineBaseFrameDecoder 的简单实现:

 public class CmdHandlerInitializer extends ChannelInitializer<Channel> {

     @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 添加解码器,
pipeline.addLast(new CmdDecoder(65 * 1024));
pipeline.addLast(new CmdHandler());
} public static final class Cmd {
private final ByteBuf name; // 名字
private final ByteBuf args; // 参数 public Cmd(ByteBuf name, ByteBuf args) {
this.name = name;
this.args = args;
} public ByteBuf name() {
return name;
} public ByteBuf args() {
return args;
}
} /**
* 根据分隔符将消息解码成Cmd对象传给下一个处理器
*/
public static final class CmdDecoder extends LineBasedFrameDecoder { public CmdDecoder(int maxLength) {
super(maxLength);
} @Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
// 通过结束分隔符从 ByteBuf 提取帧
ByteBuf frame = (ByteBuf)super.decode(ctx, buffer);
if(frame == null)
return null;
int index = frame.indexOf(frame.readerIndex(), frame.writerIndex(), (byte)' ');
// 提取 Cmd 对象
return new Cmd(frame.slice(frame.readerIndex(), index),
frame.slice(index+1, frame.writerIndex()));
}
} public static final class CmdHandler extends SimpleChannelInboundHandler<Cmd> { @Override
protected void channelRead0(ChannelHandlerContext ctx, Cmd msg) throws Exception {
// 处理 Cmd 信息
} }
}

  上面的例子主要实现了利用换行符‘\n’分隔帧,然后将每行数据解码成一个 Cmd 实例。

二、基于长度的协议

  基于长度的协议在帧头定义了一个帧编码的长度,而不是在结束位置用一个特殊的分隔符来标记。Netty 提供了两种编码器,用于处理这种类型的协议,如下:

  

  FixedLengthFrameDecoder 的操作是提取固定长度每帧 8 字节,如下图所示:

  

  但大部分时候,我们会把帧的大小编码在头部,这种情况可以使用 LengthFieldBaseFrameDecoder,它会提取帧的长度并根据长度读取帧的数据部分,如下:

  

  下面是 LengthFieldBaseFrameDecoder 的一个简单应用:

 /**
* 基于长度的协议
* LengthFieldBasedFrameDecoder
*/
public class LineBasedHandlerInitializer extends ChannelInitializer<Channel> { @Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 用于提取基于帧编码长度8个字节的帧
pipeline.addLast(new LengthFieldBasedFrameDecoder(65*1024, 0, 8));
pipeline.addLast(new FrameHandler());
} public static final class FrameHandler extends SimpleChannelInboundHandler<ByteBuf> { @Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
// TODO 数据处理
} } }

  上面的例子主要实现了提取帧首部 8 字节的长度,然后提取数据部分进行处理。

Netty入门(十)解码分隔符和基于长度的协议的更多相关文章

  1. Netty中解码基于分隔符的协议和基于长度的协议

    在使用Netty的过程中,你将会遇到需要解码器的基于分隔符和帧长度的协议.本节将解释Netty所提供的用于处理这些场景的实现. 基于分隔符的协议 基于分隔符的(delimited)消息协议使用定义的字 ...

  2. Netty学习摘记 —— 心跳机制 / 基于分隔符和长度的协议

    本文参考 本篇文章是对<Netty In Action>一书第十一章"预置的ChannelHandler和编解码器"的学习摘记,主要内容为通过 SSL/TLS 保护 N ...

  3. Netty入门与实战教程总结分享

    前言:都说Netty是Java程序员必须要掌握的一项技能,带着不止要知其然还要知其所以然的目的,在慕课上找了一个学习Netty源码的教程,看了几章后着实有点懵逼.虽然用过Netty,并且在自己的个人网 ...

  4. Netty(四)分隔符与定长解码器的使用

    TCP以流的形式进行数据传输,上层的应用协议为了对消息进行划分,往往采用如下的4种方式. (1)消息长度固定,累计读到长度总和为定长len的报文后,就认为读取到了一个完整的消息:然后重新开始读取下一个 ...

  5. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

  6. Netty入门

    一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...

  7. Netty入门——客户端与服务端通信

    Netty简介Netty是一个基于JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性.换句话说,Netty是一个NIO框架,使用它可以简单快速 ...

  8. 【原创】NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示

    前言 NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能.这其中最流行的无非就是MINA和Netty了,MINA目前的主要版本是MINA2.而Netty的主要版本是Netty3和Netty ...

  9. netty 入门二 (传输bytebuf 或者pojo)

    基于流的数据传输:在基于流的传输(如TCP / IP)中,接收的数据被存储到套接字接收缓冲器中. 不幸的是,基于流的传输的缓冲区不是数据包的队列,而是字节队列. 这意味着,即使您将两个消息作为两个独立 ...

随机推荐

  1. [日常] go语言圣经-声明,变量,赋值,类型,包和文件习题

    go语言圣经-声明1.四种类型的声明语句:var.const.type和func,分别对应变量.常量.类型和函数实体对象的声明2.包一级声明语句声明的名字可在整个包对应的每个源文件中访问,局部声明的名 ...

  2. leetcode958二叉树的完全检验-java

    最近项目刚刚检查了,又有时间刷leetcode了,一道中等的树1个小时才通过,太久不做了.. 给定一个二叉树,确定它是否是一个完全二叉树. 百度百科中对完全二叉树的定义如下: 若设二叉树的深度为 h, ...

  3. Spring Security(一)

    Spring Security(一) 基本原理 前言 Spring Security核心功能 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) Srping Security基本原理 项目 ...

  4. 不要62(hdu2089)

    不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  5. Humble Numbers(hdu1058)

    Humble Numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  6. input不可编辑且颜色不变

    <input name="ly_qq" type="text" tabindex="2" onMouseOver="this ...

  7. Codeforces Round #545 (Div. 1) 简要题解

    这里没有翻译 Codeforces Round #545 (Div. 1) T1 对于每行每列分别离散化,求出大于这个位置的数字的个数即可. # include <bits/stdc++.h&g ...

  8. css3 content 特殊字符和符号

    基本形状 ▲ 9650 25B2 ► 9658 25BA ► 9658 25BA ▼ 9660 25BC◄ 9668 25C4 ❤ 10084 2764 ✈ 9992 2708 ★ 9733 2605 ...

  9. 全局eslint不生效的处理

    react项目里能用上 eslint 的 airbnb 规范真是的,对自己的编码有很好的帮助,不经可以养成良好的代码风格,而且还能检测出 state或者变量 是否 使用过, 然而,所在团队的小伙伴们, ...

  10. 开源项目管理工具KanBoard

    KanBoard是一个很好用的项目管理软件,地址点此.它以网页形式存储在服务器或者本地,支持多标签.多项目.多用户和多种显示方式.编辑方式上支持markdown.它还提供多角度可视化的项目统计分析. ...