1、netty的编码和解码,在数据传输的时候,考虑数据安全,数据完整性都是很有必要的。这里主要是介绍netty3和netty5的编解码方式。其实从StringEncoder和StringDecoder中也可以获取源码的编解码规则。然后改变成自己的编解码规则也是可以的。

  2、netty3和netty5的编解码方式还是存在一定差别的。个人感觉netty5来的更加实用和方便。

  3、netty3的编解码规则

  1)数据编码规则(我这里只是用于显示,数据规则很简单)

  包头+模块+数据(请求编解码)

  包头+模块+状态+数据(响应编解码)

  2)目录

  

  3)请求和相应对象

package com.troy.data.domain;

//请求数据
public class Request { //模块类型
private int model;
//数据
private byte[] data; public int getModel() {
return model;
} public void setModel(int model) {
this.model = model;
} public byte[] getData() {
return data;
} public void setData(byte[] data) {
this.data = data;
} @Override
public String toString() {
return "Request{" +
"model=" + model +
", data=" + new String(data) +
'}';
}
}
package com.troy.data.domain;

import java.util.Arrays;

//响应数据
public class Response { //模块类型
private int model;
//状态码
private int status;
//数据
private byte[] data; public int getModel() {
return model;
} public void setModel(int model) {
this.model = model;
} public int getStatus() {
return status;
} public void setStatus(int status) {
this.status = status;
} public byte[] getData() {
return data;
} public void setData(byte[] data) {
this.data = data;
} @Override
public String toString() {
return "Response{" +
"model=" + model +
", status=" + status +
", data=" + new String(data) +
'}';
}
}

  4)常量(这里的包头,因为是固定的就写了一个常量)

package com.troy.data.constant;

//常量
public class ConsantUtil { //固定常量用于数据拼接,确认
public static final int PACKAGE_HEADER = -; }

  5)请求编解码

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Request;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; public class RequestEncode extends OneToOneEncoder { protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception { Request request = (Request) o;
ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer();
channelBuffer.writeInt(ConsantUtil.PACKAGE_HEADER);
channelBuffer.writeInt(ConsantUtil.PACKAGE_HEADER);
channelBuffer.writeBytes(request.getData());
return channelBuffer;
}
}
package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Request;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder; //请求数据解码
public class RequestDecode extends OneToOneDecoder { protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
ChannelBuffer channelBuffer = (ChannelBuffer) o;
if (ConsantUtil.PACKAGE_HEADER == channelBuffer.readInt()) {
Request request = new Request();
request.setModel(channelBuffer.readInt());
byte[] bytes = new byte[channelBuffer.readableBytes()];
channelBuffer.readBytes(bytes);
request.setData(bytes);
return request;
}
return null;
}
}

  6)响应编解码

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Response;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; //响应编码器
public class ResponseEncode extends OneToOneEncoder { protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
Response response = (Response) o;
ChannelBuffer channelBuffer = ChannelBuffers.dynamicBuffer();
channelBuffer.writeInt(ConsantUtil.PACKAGE_HEADER);
channelBuffer.writeInt(response.getModel());
channelBuffer.writeInt(response.getStatus());
channelBuffer.writeBytes(response.getData());
return channelBuffer;
}
}
package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Response;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder; //响应解码
public class ResponseDecode extends OneToOneDecoder{ protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
ChannelBuffer channelBuffer = (ChannelBuffer) o;
if (ConsantUtil.PACKAGE_HEADER == channelBuffer.readInt()) {
Response response = new Response();
response.setModel(channelBuffer.readInt());
response.setStatus(channelBuffer.readInt());
byte[] bytes = new byte[channelBuffer.readableBytes()];
channelBuffer.readBytes(bytes);
response.setData(bytes);
return response;
}
return null;
}
}

  7)设置对应的管道编解码就可以了

  a、客户端

     //设置管道工厂
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline channelPipeline = Channels.pipeline();
channelPipeline.addLast("decode",new RequestEncode());
channelPipeline.addLast("encode",new ResponseDecode());
channelPipeline.addLast("client",new ClientHandler());
return channelPipeline;
}
});
  @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Response response = (Response) e.getMessage();
System.out.println(response.toString());
super.messageReceived(ctx, e);
}

  b、服务端

        //设置管道流
serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline channelPipeline = Channels.pipeline();
//添加处理方式
channelPipeline.addLast("idle",new IdleStateHandler(new HashedWheelTimer(),,,));
channelPipeline.addLast("decode",new RequestDecode());
channelPipeline.addLast("encode",new ResponseEncode());
channelPipeline.addLast("server",new ServerHandler());
return channelPipeline;
}
});
  @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Request request = (Request) e.getMessage();
System.out.println("client:"+request.toString());
Response response = new Response();
response.setModel();
response.setStatus();
response.setData("hello client".getBytes());
ctx.getChannel().write(response);
super.messageReceived(ctx, e);
}

  4、netty5的编解码规则

  1)数据结构、目录结构、对象、常量都是一样。

  2)编解码的编写方式有些不一样

  a、请求编解码

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Request;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder; import java.util.List;
@ChannelHandler.Sharable
public class RequestEncode extends MessageToMessageEncoder<Request> { protected void encode(ChannelHandlerContext channelHandlerContext, Request request, List<Object> list) throws Exception {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt(ConsantUtil.PACKAGE_HEADER);
byteBuf.writeInt(request.getModel());
byteBuf.writeBytes(request.getData());
list.add(byteBuf);
}
}

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Request;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder; import java.util.List; //请求数据解码
@ChannelHandler.Sharable
public class RequestDecode extends MessageToMessageDecoder<ByteBuf>{ protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
if (ConsantUtil.PACKAGE_HEADER == byteBuf.readInt()) {
//当数据超过指定值的时候跳过这部分数据
if (byteBuf.readableBytes() > ) {
byteBuf.skipBytes(byteBuf.readableBytes());
}
//一个字节一个字节的读取,知道读取到包头
while(true) {
byteBuf.markReaderIndex();
if (ConsantUtil.PACKAGE_HEADER == byteBuf.readInt()) {
break;
}
byteBuf.resetReaderIndex();
byteBuf.readByte();
}
Request request = new Request();
request.setModel(byteBuf.readInt());
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
request.setData(bytes);
list.add(request);
}
}
}

  b、响应编解码

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Response;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder; import java.util.List; //响应编码器
@ChannelHandler.Sharable
public class ResponseEncode extends MessageToMessageEncoder<Response> { protected void encode(ChannelHandlerContext channelHandlerContext, Response response, List<Object> list) throws Exception {
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeInt(ConsantUtil.PACKAGE_HEADER);
byteBuf.writeInt(response.getModel());
byteBuf.writeInt(response.getStatus());
byteBuf.writeBytes(response.getData());
list.add(byteBuf);
}
}

package com.troy.data.codec;

import com.troy.data.constant.ConsantUtil;
import com.troy.data.domain.Response;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder; import java.util.List; //响应解码
@ChannelHandler.Sharable
public class ResponseDecode extends MessageToMessageDecoder<ByteBuf>{ protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
if (ConsantUtil.PACKAGE_HEADER == byteBuf.readInt()) {
//当数据超过指定值的时候跳过这部分数据
if (byteBuf.readableBytes() > ) {
byteBuf.skipBytes(byteBuf.readableBytes());
}
//一个字节一个字节的读取,知道读取到包头
while(true) {
byteBuf.markReaderIndex();
if (ConsantUtil.PACKAGE_HEADER == byteBuf.readInt()) {
break;
}
byteBuf.resetReaderIndex();
byteBuf.readByte();
}
Response response = new Response();
response.setModel(byteBuf.readInt());
response.setStatus(byteBuf.readInt());
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
response.setData(bytes);
list.add(response);
}
}
}

  3)处理上面基本上都是一样的。

  5、netty的编解码,主要目的就是处理通讯问题,对数据进行自定义处理!

  6、源码下载:https://pan.baidu.com/s/1nvUnmEt

netty之编解码的更多相关文章

  1. Netty入门系列(3) --使用Netty进行编解码的操作

    前言 何为编解码,通俗的来说,我们需要将一串文本信息从A发送到B并且将这段文本进行加工处理,如:A将信息文本信息编码为2进制信息进行传输.B接受到的消息是一串2进制信息,需要将其解码为文本信息才能正常 ...

  2. java架构之路-(netty专题)netty的编解码(出入战)与粘包拆包

    上次回归: 上次博客我们主要说了netty的基本使用,都是一些固定的模式去写的,我们只需要关注我们的拦截器怎么去写就可以了,然后我们用我们的基础示例,改造了一个简单的聊天室程序,可以看到内部加了一个S ...

  3. Netty 编解码技术 数据通信和心跳监控案例

    Netty 编解码技术 数据通信和心跳监控案例 多台服务器之间在进行跨进程服务调用时,需要使用特定的编解码技术,对需要进行网络传输的对象做编码和解码操作,以便完成远程调用.Netty提供了完善,易扩展 ...

  4. Netty 源码 ChannelHandler(四)编解码技术

    Netty 源码 ChannelHandler(四)编解码技术 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一.拆包与粘 ...

  5. 【转】Netty系列之Netty编解码框架分析

    http://www.infoq.com/cn/articles/netty-codec-framework-analyse/ 1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称 ...

  6. Netty系列之Netty编解码框架分析

    1. 背景 1.1. 编解码技术 通常我们也习惯将编码(Encode)称为序列化(serialization),它将对象序列化为字节数组,用于网络传输.数据持久化或者其它用途. 反之,解码(Decod ...

  7. netty源码解解析(4.0)-19 ChannelHandler: codec--常用编解码实现

    数据包编解码过程中主要的工作就是:在编码过程中进行序列化,在解码过程中从Byte流中分离出数据包然后反序列化.在MessageToByteEncoder中,已经解决了序列化之后的问题,ByteToMe ...

  8. Netty对常用编解码的支持

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! Netty对编解码的支持 打开Netty的源码,它对很多的编码器都提 ...

  9. Netty 编解码奥秘

    Netty中编解码 Netty 的解码器有很多种,比如基于长度的,基于分割符的,私有协议的.但是,总体的思路都是一致的. 拆包思路:当数据满足了 解码条件时,将其拆开.放到数组.然后发送到业务 han ...

随机推荐

  1. Github 删除 repository

    Github 删除 repository 如下图操作

  2. IO流输入输出流,字符字节流

    一.流 1.流的概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. ...

  3. es6之decorator

    //decorator //第三方库为:core-decorators //以下为代码实例 { //decorator //修饰器是一个函数 //是修改一个行为 //修改一个类的行为 console. ...

  4. 【SPJ6285 NGM2 - Another Game With Numbers】 题解

    题目链接:https://www.luogu.org/problemnew/show/SP6285 唉好久之前校内模拟赛的题目 嘴上说着明白但是实现起来我的位运算太丑陋了啊! #include < ...

  5. 如果有人问你CAP理论是什么,就把这篇文章发给他。

    绝对和你在网上看到的CAP定理介绍不一样. CAP 定理(CAP theorem)又被称作布鲁尔定理(Brewer's theorem),是加州大学伯克利分校的计算机科学家埃里克·布鲁尔(Eric B ...

  6. WebApiClient.AOT.dll 调用api地址 -> 调用方法

    优点:简化api调用过程,WebApiClient.AOT.dll中的IHttpApi接口 缺点:只适用于内部服务之间的调用(没有验证过程) 1.继承IHttpAPi接口 public interfa ...

  7. [转]收集Oracle UNDO诊断信息脚本

    使用该脚本可收集与undo相关的信息,在undo表空间出问题时可使用该脚本来诊断. 使用方法: 1.将脚本拷贝到服务器,创建文件保存,文件名可随意取,例如:diag.out 2.以sys用户登录数据库 ...

  8. 微信小程序 | 未来O2O电商的“阴谋”

    发展历史 2016年1月11日,微信之父张小龙时隔多年的公开亮相,提出了公众号服务的短板,而透露微信内部正在研发的新形态工具,称之"微信小程序". 2016年9月21日,微信小程序 ...

  9. acm--1006

    Problem Description The three hands of the clock are rotating every second and meeting each other ma ...

  10. 基于LSB的图像数字水印实验

    1. 实验类别 设计型实验:MATLAB设计并实现基于LSB的图像数字水印算法. 2. 实验目的 了解信息隐藏中最常用的LSB算法的特点,掌握LSB算法原理,设计并实现一种基于图像的LSB隐藏算法. ...