背景:部标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. 数据攻略●R语言自述

    (注明:以下文章均在Linux操作系统下执行) 一.R语言简介 R语言是用于统计分析,图形表示和报告的编程语言和软件环境.R语言由Ross Ihaka和Robert Gentleman在新西兰奥克兰大 ...

  2. 论JVM爆炸的几种姿势及自救方法,你不得不知!

    前言 如今不管是在面试还是在我们的工作中,OOM总是不断的出现在我们的视野中,所以我们有必要去了解一下导致OOM的原因以及一些基本的调整方法,大家可以通过下面的事例来了解一下什么样的代码会导致OOM, ...

  3. B+树的Copy-on-Write设计

    本文主要介绍B+树的Copy-On-Write,包括由来.设计思路和核心源码实现(以Xapian源码为例).中文的互联网世界里,对B树.B+树的科普介绍很丰富,但对它们在工业界的实际使用却几乎没有相关 ...

  4. Scala安装教程

    首先去Java官网下载Java的安装包 jdk-8u121-windows-x64.exe 再去Scala官网下载Scala的安装包 Scala2.12.1 安装Java: 配置Java环境变量(系统 ...

  5. Eclipse导入别人的项目报错:Unable to load annotation processor factory 'xxxxx.jar' for project

    使用eclipse导入别人的项目时候,报错Unable to load annotation processor factory 'xxxxx.jar' for project. 解决方案 1.项目右 ...

  6. 什么是SOAP,有哪些应用

    SOAP 是一种轻量级协议,用于在分散型.分布式环境中交换结构化信息. SOAP 利用 XML 技术定义一种可扩展的消息处理框架,它提供了一种可通过多种底层协议进行交换的消息结构. 这种框架的设计思想 ...

  7. SQL语句查询表结构

    SQL语句查询表结构   刚刚在做一个小项目,数据库中一张表有20来个字段,用我以前做的一个.NET实体类生成器一个一个的输入还是闲麻烦,于是打算找个时间来重新的改造一个那个.NET实体类,能够通过选 ...

  8. 简单的SQL注入之2

    Topic Link http://ctf5.shiyanbar.com/web/index_2.php 一.方法One sqlmap直接跑出来 1)暴库 2)爆表 3)爆段 4) 结果 二.方法Tw ...

  9. gcc编译基本用法~2

    编译简单的 C 程序 C 语言经典的入门例子是 Hello World,下面是一示例代码: ;} 我们假定该代码存为文件‘hello.c’.要用 gcc 编译该文件,使用下面的命令: $ gcc -g ...

  10. Docker系列04—Docker的网络模式详解

    本文收录在容器技术学习系列文章总目录 1.Docker的四种网络模式 (1)docker四种网络模式如下: Bridge contauner   桥接式网络模式 Host(open) containe ...