背景:部标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. 交叉编译 tcpdump

    目录 1. 下载 tcpdump 2. 交叉编译 3. 相关说明 1. 下载 tcpdump 官网:http://www.tcpdump.org/ 2. 交叉编译 交叉编译libpcap: $ wge ...

  2. Python档案袋(函数与函数装饰器 )

    特点:代码复用.可扩展.保持一致性 函数简单的实现,返回值的不同: #定义方法 def funx1(): pass def funx2(): return 0 def funx3(): return ...

  3. Java Runtime.exec()的使用

    Sun的doc里其实说明还有其他的用法: exec(String[] cmdarray, String[] envp, File dir) Executes the specified command ...

  4. Android--操作图片Exif信息

    前言 在Android系统中,图片文件在内存中以像素点的二维数组加载,存放像素信息,还会在开头加上一些额外的照片拍摄参数信息,这些信息就是Exif.Android2.0之后,媒体库加入了操作图片Exi ...

  5. 玩转C线性表和单向链表之Linux双向链表优化

    前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...

  6. C++STL模板库序列容器之vector

    目录 STL之Vecter 一丶STL简介 二丶Vector用法 1.vector容器的使用 2.vector迭代器. 3.vector中的方法. 三丶常用算法 1.常见算法中的算法方法. 2.sor ...

  7. [React] react+redux+router+webpack+antd环境搭建一版

    好久之前搭建的一个react执行环境,受历史影响是webpack3.10.0和webpack-dev-server2.7.1的环境,新项目准备用webpack4重新弄弄了,旧的记录就合并发布了(在没有 ...

  8. IO通信模型(二)同步非阻塞模式NIO(NonBlocking IO)

    同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,发出Socket的accept()和read()操作时,如果内核中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回一个信息.也 ...

  9. VisualStudio,用C#写的一个开源移动APP,资产管理类项目SmoSec

    继SmoOne之后,Smobiler团队又推出一款用C#开发的APP开源项目. 这款开源项目名为SmoSec,目前包含资产管理.耗材管理两大类. 并且,未来会不断迭代,持续增加盘点.标签打印和仓库管理 ...

  10. 6.JAVA-链表实例

    1.实现链表的步骤 1).实现Node节点类(用来保存链表中每个节点的数据,以及下一个节点成员) 2).实现LinkList链表类(用来封装Node节点类,和用户实现交互) 3).在LinkList类 ...