背景:部标GPS通讯底层全部改造成基于Netty服务器实现的,现将Mina的依赖移除,修改过程中有用到缓冲区的读写。现做了如下修改:

原有基于Mina的IoBuffer对字节读写封装代码如下:

 package com.hns.gps.gw.jt808.protocol;

 import com.hns.gps.gw.jt808.utils.Tools;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer; import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset; public class MyBuffer {
private Logger logger = Logger.getLogger(MyBuffer.class);
IoBuffer buff; public MyBuffer() {
buff.setUseDirectBuffer(false);
buff = IoBuffer.allocate(1536);
buff.mark();
} public MyBuffer(int len) {
buff.setUseDirectBuffer(false);
buff = IoBuffer.allocate(len);
buff.mark();
} public MyBuffer(byte[] bytes) {
if (bytes.length > 1024)
buff = IoBuffer.allocate(bytes.length + 100);
else
buff = IoBuffer.allocate(1024);
buff.mark();
buff.put(bytes);
buff.limit(bytes.length);
buff.reset();
}
public MyBuffer(byte[] bytes, int start, int length) {
buff = IoBuffer.allocate(length);
buff.mark();
buff.put(bytes, start, length);
buff.limit(length);
buff.reset();
} public void clear() {
buff.clear();
buff.mark();
} public void put(byte a) {
buff.put(a);
} public void put(long a)
{
buff.putLong(a);
} public void put(short a) {
buff.putShort(a);
} public void put(byte[] a) {
buff.put(a);
} public boolean hasRemain() {
return buff.remaining() > 0;
} public void put(int a) {
buff.putInt(a);
} public void putShort(int a) {
buff.putShort((short) a);
} public void put(String str) {
// US-ASCII try {
byte[] b = str.getBytes("gbk");
buff.put(b); } catch (Exception e) {
// logger.error(e.getMessage(), e);
}
} public void putBcd(String str, int length)
{
byte[] b = BcDToBytes(str,length);
buff.put(b);
} public static String BytesToBcd(byte[] bytes, int start, int len) {
StringBuilder bcd = new StringBuilder();
for (int m = 0; m < len; m++) {
bcd.append(String.format("%02X", bytes[start + m]));
}
return bcd.toString();
} public static byte[] BcDToBytes(String bcd, int len) {
bcd = bcd == null ? "" : bcd;
while (bcd.length() < len) {
bcd = "0" + bcd;
}
return Tools.HexString2Bytes(bcd);
} public void put(String str, int len) {
byte[] result = new byte[len];
try {
byte[] b = str.getBytes("gbk"); System.arraycopy(b, 0, result, 0, b.length); for (int m = b.length; m < len; m++) {
result[m] = 0;
}
buff.put(result); } catch (Exception e) {
//logger.error(e.getMessage(), e);
}
} public byte get() {
return buff.get();
} public byte[] gets(int len) {
byte[] data = new byte[len];
buff.get(data);
return data;
} public int getInt() {
return buff.getInt();
} public short getShort() {
return buff.getShort();
} public long getLong() {
return buff.getLong();
} // 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。
public int getUnsignedShort() {
short t = buff.getShort();
return t & 0xffff;
} // 将data字节型数据转换为0~255 (0xFF 即BYTE)。
public int getUnsignedByte() {
return buff.get() & 0x0FF;
} public long getUnsignedInt() {
return buff.getInt() & 0x0FFFFFFFF;
} public String getString() {
try {
String strTemp = buff
.getString(Charset.forName("GBK").newDecoder());
return strTemp;
} catch (CharacterCodingException e) {
e.printStackTrace();
}
return "";
} public String getString(int len) {
try {
String strTemp = buff.getString(len, Charset.forName("GBK")
.newDecoder());
return strTemp;
} catch (CharacterCodingException e) {
e.printStackTrace();
gets(len);
}
return "";
} public String getBcdString(int len) {
byte[] bytes = this.gets(len);
StringBuilder bcd = new StringBuilder();
for (int m = 0; m < len; m++) {
bcd.append(String.format("%02X", bytes[m]));
}
return bcd.toString();
} public byte[] array() {
int pos = buff.position();
byte[] data = new byte[pos];
buff.reset();
buff.get(data);
return data;
} public static void main(String[] args) { IoBuffer ib = IoBuffer.allocate(1024);
ib.mark();
ib.put((byte) 128);
ib.reset();
// byte b = ib.get();
// int x = b& 0xff;
short x = ib.getUnsigned(); short y = ib.getUnsigned(0); System.out.println("" + x + "," + y);
} }

后修改成Netty版的ByteBuffer操作实现如下:

 package com.hns.gps.gw.jt808.protocol;

 import com.hns.gps.gw.jt808.utils.Tools;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.ResourceLeakDetector;
import org.apache.log4j.Logger; import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; /**
* ByteBuffer缓冲区,用Netty实现
*
* @author linys
* @create 2018-06-12
* @since 1.0.0
*/
public class ByteBuffer {
private Logger logger = Logger.getLogger(ByteBuffer.class);
protected ByteBuf buff; public ByteBuffer() {
buff = ByteBufAllocator.DEFAULT.ioBuffer(1536);
//为了找到ByteBuff没有被释放的原因 (上线关闭)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
} public ByteBuffer(byte[] bytes) {
buff = ByteBufAllocator.DEFAULT.ioBuffer(bytes.length);
buff.writeBytes(bytes);
//为了找到ByteBuff没有被释放的原因 (上线关闭)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
} public ByteBuffer(byte[] bytes, int start, int length) {
buff = ByteBufAllocator.DEFAULT.ioBuffer(length);
buff.writeBytes(bytes, start, length);
//为了找到ByteBuff没有被释放的原因 (上线关闭)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
} public void clear() {
buff.clear();
buff.markWriterIndex();
buff.markReaderIndex();
} public void put(byte a) {
buff.writeByte(a);
} public void put(long a) {
buff.writeLong(a);
} public void put(short a) {
buff.writeShort(a);
} public void put(byte[] a) {
buff.writeBytes(a);
} public boolean hasRemain() {
return buff.isReadable();
} public void put(int a) {
buff.writeInt(a);
} public void put(String str) {
// US-ASCII
try {
byte[] b = str.getBytes("gbk");
buff.writeBytes(b);
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
}
} public String getBcdString(int len) {
byte[] bytes = this.gets(len);
StringBuilder bcd = new StringBuilder();
for (int m = 0; m < len; m++) {
bcd.append(String.format("%02X", bytes[m]));
}
return bcd.toString();
} public void putBcd(String str, int length) {
byte[] b = BcDToBytes(str, length);
buff.writeBytes(b);
} public static byte[] BcDToBytes(String bcd, int len) {
bcd = bcd == null ? "" : bcd;
while (bcd.length() < len) {
bcd = "0" + bcd;
}
return Tools.HexString2Bytes(bcd);
} public static String BytesToBcd(byte[] bytes, int start, int len) {
StringBuilder bcd = new StringBuilder();
for (int m = 0; m < len; m++) {
bcd.append(String.format("%02X", bytes[start + m]));
}
return bcd.toString();
} public void put(String str, int len) {
byte[] result = new byte[len];
try {
byte[] b = str.getBytes("gbk");
System.arraycopy(b,0, result,0, b.length);
for (int m = b.length; m < len; m++) {
result[m] = 0; //不够位补0
}
buff.writeBytes(result);
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
}
} public byte get() {
return buff.readByte();
} public short getShort() {
return buff.readShort();
} public int getInt() {
return buff.readInt();
} public long getLong() {
return buff.readLong();
} public double getDouble() {
return buff.readDouble();
} public byte[] gets(int len) {
byte[] data = new byte[len];
buff.readBytes(data);
return data;
} // 将data字节型数据转换为0~255 (0xFF 即BYTE)。
public short getUnsignedByte() {
return buff.readUnsignedByte();
} // 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。
public int getUnsignedShort() {
return buff.readUnsignedShort();
} public long getUnsignedInt() {
return buff.readUnsignedInt();
} public String getString() {
return buff.toString(Charset.forName("GBK"));
} public String getString(int len) {
return buff.toString(0, len, Charset.forName("GBK"));
} /**
* 转换成byte数组
* @return
*/
public byte[] toByteArray() {
int pos = buff.writerIndex();
byte[] data = new byte[pos];
buff.readBytes(data);
//再次调用重新从头读
buff.resetReaderIndex();
return data;
} /**
* 清空释放buff,在buff使用结束后调用
* @return
*/
public void release() {
this.clear();
//释放缓冲区内存
ReferenceCountUtil.release(buff);
} /**
* 转换成byte数组并清空释放buff,在buff使用结束后调用
* @return
*/
public byte[] toByteArrayAndRelease() {
int pos = buff.writerIndex();
byte[] data = new byte[pos];
buff.readBytes(data);
this.clear();
//释放缓冲区内存
ReferenceCountUtil.release(buff);
return data;
} }

总结:处理网络数据的项目中经常需要处理字节数据,Java的ByteBuffer很强大,对于NIO的ByteBuffer字节读写缓冲区操作,Mina和Netty都有封装,IoBuffer基于Java原生ByteBuffer封装而成,ByteBuff则是Netty自己独有的字节数据Buffer,Netty提供了更强大的封装并能实现零拷贝,更加方便我们操作字节缓冲区,推荐使用netty的ByteBuff!代码供大家对ByteBuff的封装参考。

文章封装的代码基于连接:

https://blog.csdn.net/alex_bean/article/details/51251015

https://blog.csdn.net/u010853261/article/details/53690780

https://www.cnblogs.com/zzt-lovelinlin/p/5292608.html

Mina的IoBuffer改造成Netty的ByteBuff的更多相关文章

  1. MINA系列学习-IoBuffer

    在阅读IoBuffer源码之前,我们先看Mina对IoBuffer的描述:A byte buffer used by MINA applications. This is a replacement ...

  2. Mina、Netty、Twisted一起学(四):定制自己的协议

    在前面的博文中,介绍一些消息分割的方案,以及MINA.Netty.Twisted针对这些方案提供的相关API.例如MINA的TextLineCodecFactory.PrefixedStringCod ...

  3. 【MINA】缓存区ByteBuffer和IOBuffer你要了解的常用知识

    mina中IOBuffer是Nio中ByteBuffer的衍生类,主要是解决Bytebuffer的两个不足 1.没有提供足够灵活的get/putXXX方法 2.它容量固定,难以写入可变长度的数据 特点 ...

  4. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  5. Mina、Netty、Twisted一起学(六):session

    开发过Web应用的同学应该都会使用session.由于HTTP协议本身是无状态的,所以一个客户端多次访问这个web应用的多个页面,服务器无法判断多次访问的客户端是否是同一个客户端.有了session就 ...

  6. Java NIO框架Mina、Netty、Grizzly介绍与对比(zz)

    Mina:Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用 ...

  7. Java NIO框架Mina、Netty、Grizzly介绍与对比

    Mina:Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用 ...

  8. Mina源码阅读笔记(二)- IoBuffer的封装

    在阅读IoBuffer源码之前,我们先看Mina对IoBuffer的描述:A byte buffer used by MINA applications. This is a replacement ...

  9. Java NIO框架 Mina、Netty、Grizzly

    Mina Mina(Multipurpose Infrastructure for Network Applications) 是 Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程 ...

随机推荐

  1. python高级-迭代器(18)

    一.什么是迭代器 迭代是访问集合元素的⼀种⽅式. 迭代器是⼀个可以记住遍历的位置的对象. 迭代器对象从集合的第⼀个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退 二.可迭代对象 直 ...

  2. ThinkPHP 数据库操作(七) : 视图查询、子查询、原生查询

    视图查询 视图查询可以实现不依赖数据库视图的多表查询,并不需要数据库支持视图,例如: Db::view('User','id,name') ->view('Profile','truename, ...

  3. andrroid 测试那点事

    1.拨号*#*#98284#*#* 2.查看imei号:拔号 *#06# 3.抓取 MTK Log *#*#3646633#*#* 高通平台 *#62564# 4.查看手机的cpu架构信息:adb s ...

  4. 《HelloGitHub》第 12 期

    <HelloGitHub>第 12 期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 简介 最开始我只是想把自己在浏览 GitHub 过程中,发现的有意思.高 ...

  5. 你的第一个Django程序

    本文使用Pycharm.Django 2.0.9.Python 3.6环境,本文大纲 建立Django项目 建立页面 什么是URLconf和ROOT_URLCONF Django怎么处理URL请求 关 ...

  6. 大众美团服务链监控CAT

    github链接:https://github.com/dianping/cat CAT 作为服务端项目基础组件,提供了 Java, C/C++, Node.js, Python, Go 等多语言客户 ...

  7. ASP.NET Core 2.1 : 十一. 如何在后台运行一个任务

    在大部分程序中一般都会需要用到后台任务, 比如定时更新缓存或更新某些状态.(ASP.NET Core 系列目录) 一.应用场景 以调用微信公众号的Api为例, 经常会用到access_token,官方 ...

  8. Docker最全教程——从理论到实战(五)

    往期内容链接 Docker最全教程——从理论到实战(一) Docker最全教程——从理论到实战(二) Docker最全教程——从理论到实战(三) Docker最全教程——从理论到实战(四) 本篇教程持 ...

  9. [四] JavaIO之类层次体系结构横向比对

      IO家族类层次体系结构横向匹配   上一篇文章中主要介绍了JavaIO流家族的整体设计思路,简单回顾下 基本逻辑涉及数据源 流的方向,以及流的数据形式这三个部分的组合 按照流的数据形式和流的方向, ...

  10. Spring Boot(九)Swagger2自动生成接口文档和Mock模拟数据

    一.简介 在当下这个前后端分离的技术趋势下,前端工程师过度依赖后端工程师的接口和数据,给开发带来了两大问题: 问题一.后端接口查看难:要怎么调用?参数怎么传递?有几个参数?参数都代表什么含义? 问题二 ...