Mina的IoBuffer改造成Netty的ByteBuff
背景:部标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的更多相关文章
- MINA系列学习-IoBuffer
在阅读IoBuffer源码之前,我们先看Mina对IoBuffer的描述:A byte buffer used by MINA applications. This is a replacement ...
- Mina、Netty、Twisted一起学(四):定制自己的协议
在前面的博文中,介绍一些消息分割的方案,以及MINA.Netty.Twisted针对这些方案提供的相关API.例如MINA的TextLineCodecFactory.PrefixedStringCod ...
- 【MINA】缓存区ByteBuffer和IOBuffer你要了解的常用知识
mina中IOBuffer是Nio中ByteBuffer的衍生类,主要是解决Bytebuffer的两个不足 1.没有提供足够灵活的get/putXXX方法 2.它容量固定,难以写入可变长度的数据 特点 ...
- 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?
[读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...
- Mina、Netty、Twisted一起学(六):session
开发过Web应用的同学应该都会使用session.由于HTTP协议本身是无状态的,所以一个客户端多次访问这个web应用的多个页面,服务器无法判断多次访问的客户端是否是同一个客户端.有了session就 ...
- Java NIO框架Mina、Netty、Grizzly介绍与对比(zz)
Mina:Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用 ...
- Java NIO框架Mina、Netty、Grizzly介绍与对比
Mina:Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用 ...
- Mina源码阅读笔记(二)- IoBuffer的封装
在阅读IoBuffer源码之前,我们先看Mina对IoBuffer的描述:A byte buffer used by MINA applications. This is a replacement ...
- Java NIO框架 Mina、Netty、Grizzly
Mina Mina(Multipurpose Infrastructure for Network Applications) 是 Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程 ...
随机推荐
- Python档案袋( 进程与协程 )
Python的进程和线程是使用的操作系统的原生线程和进程,其是去调用操作系统的相应接口实现 进程:之间不可直接共享数据,是资源的集合,进程必须有一个线程 线程:基于进程,之间可直接共享数据,可执行,只 ...
- 【Storm篇】--Storm从初始到分布式搭建
一.前述 Storm是一个流式处理框架,相比较于SparkStreaming是一个微批处理框架,hadoop是一个批处理框架. 二 .搭建流程 1.集群规划 Nimbus Supervisor ...
- Hive篇--搭建Hive集群
一.前述 Hive中搭建分为三中方式 a)内嵌Derby方式 b)Local方式 c)Remote方式 三种方式归根到底就是元数据的存储位置不一样. 二.具体实现 a)内嵌Derby方式 使用derb ...
- BBS论坛(三十三)
33.celery实现邮件异步发送 (1)task.py pip install celery redis from celery import Celery from flask import Fl ...
- 『2019/4/8 TGDay1模拟赛 反思与总结』
2019/4/8 TGDay1模拟赛 这次是和高一的学长学姐们一起参加的\(TG\)模拟考,虽然说是\(Day1\),但是难度还是很大的,感觉比\(18\)年的\(Day1\)难多了. 还是看一下试题 ...
- asp.net core系列 38 WebAPI 返回类型与响应格式--必备
一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...
- Android--从系统Camera和Gallery获取图片优化
前言 之前有两篇博客讲解了如何从系统内已有的Camera和Gallery应用中获取图片的例子,看到评论里有朋友说有时候会报错,导致程序崩溃的问题.本篇博客主要就这个问题分析讲解一下,最后将以一个简单的 ...
- 从零打卡leetcode之day 4--无重复最长字符串
题目描述: 给定一个字符串,找出不含有重复字符的最长子串的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3. ...
- 看板中的WIP限制
WIP限制并不是真的要限制你的进度,事实上正相反. 什么是WIP限制? 在敏捷开发中,WIP限制决定了每种情况下的工作流中可以存续的最大工作量.限制进行中的工作数量可以更容易辨识团队工作流中的无效工作 ...
- 你以为的MongoDB副本集的高可用是真的高可用了吗?
很久没来更新博客,自感是一个只会搬砖的劳工,总搞些MySQL相关的数据库实在无聊,且时不时遇到些不讲道理的Dev吧,真的是心累至极,有种想回头我也去干开发的冲动,当个需求者有话语权要风得风,要雨得雨多 ...