Mina的IoBuffer改造成Netty的ByteBuff

2022年9月6日10:14:53

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

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

  1package com.hns.gps.gw.jt808.protocol;  2  3import com.hns.gps.gw.jt808.utils.Tools;  4import org.apache.log4j.Logger;  5import org.apache.mina.core.buffer.IoBuffer;  6  7import java.nio.charset.CharacterCodingException;  8import java.nio.charset.Charset;  9 10publicclass MyBuffer { 11private Logger logger = Logger.getLogger(MyBuffer.class); 12    IoBuffer buff; 13 14public MyBuffer() { 15         buff.setUseDirectBuffer(false); 16         buff = IoBuffer.allocate(1536); 17        buff.mark(); 18    } 19 20public MyBuffer(int len) { 21         buff.setUseDirectBuffer(false); 22         buff = IoBuffer.allocate(len); 23        buff.mark(); 24    } 25 26public MyBuffer(byte[] bytes) { 27if (bytes.length > 1024) 28             buff = IoBuffer.allocate(bytes.length + 100); 29else 30             buff = IoBuffer.allocate(1024); 31        buff.mark(); 32        buff.put(bytes); 33        buff.limit(bytes.length); 34        buff.reset(); 35    } 36public MyBuffer(byte[] bytes,int start,int length) { 37         buff = IoBuffer.allocate(length); 38        buff.mark(); 39        buff.put(bytes, start, length); 40        buff.limit(length); 41        buff.reset(); 42    } 43 44 45publicvoid clear() { 46        buff.clear(); 47        buff.mark(); 48    } 49 50publicvoid put(byte a) { 51        buff.put(a); 52    } 53 54publicvoid put(long a) 55    { 56        buff.putLong(a); 57    } 58 59publicvoid put(short a) { 60        buff.putShort(a); 61    } 62 63publicvoid put(byte[] a) { 64        buff.put(a); 65    } 66 67publicboolean hasRemain() { 68return buff.remaining() > 0; 69    } 70 71publicvoid put(int a) { 72        buff.putInt(a); 73    } 74 75publicvoid putShort(int a) { 76         buff.putShort((short) a); 77    } 78 79publicvoid put(String str) { 80// US-ASCII 81 82try { 83byte[] b = str.getBytes("gbk"); 84            buff.put(b); 85 86         }catch (Exception e) { 87//    logger.error(e.getMessage(), e); 88        } 89    } 90 91publicvoid putBcd(String str,int length) 92    { 93byte[] b = BcDToBytes(str,length); 94        buff.put(b); 95    } 96 97 98publicstatic String BytesToBcd(byte[] bytes,int start,int len) { 99         StringBuilder bcd =new StringBuilder();100for (int m = 0; m < len; m++) {101             bcd.append(String.format("%02X", bytes[start + m]));102        }103return bcd.toString();104    }105106publicstaticbyte[] BcDToBytes(String bcd,int len) {107         bcd = bcd ==null ? "" : bcd;108while (bcd.length() < len) {109             bcd = "0" + bcd;110        }111return Tools.HexString2Bytes(bcd);112    }113114publicvoid put(String str,int len) {115byte[] result =newbyte[len];116try {117byte[] b = str.getBytes("gbk");118119             System.arraycopy(b, 0, result, 0, b.length);120121for (int m = b.length; m < len; m++) {122                 result[m] = 0;123            }124            buff.put(result);125126         }catch (Exception e) {127//logger.error(e.getMessage(), e);128        }129    }130131publicbyte get() {132return buff.get();133    }134135publicbyte[] gets(int len) {136byte[] data =newbyte[len];137        buff.get(data);138return data;139    }140141publicint getInt() {142return buff.getInt();143    }144145publicshort getShort() {146return buff.getShort();147    }148149publiclong getLong() {150return buff.getLong();151    }152153// 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。154publicint getUnsignedShort() {155short t = buff.getShort();156return t & 0xffff;157    }158159// 将data字节型数据转换为0~255 (0xFF 即BYTE)。160publicint getUnsignedByte() {161return buff.get() & 0x0FF;162    }163164publiclong getUnsignedInt() {165return buff.getInt() & 0x0FFFFFFFF;166    }167168public String getString() {169try {170             String strTemp = buff171                     .getString(Charset.forName("GBK").newDecoder());172return strTemp;173         }catch (CharacterCodingException e) {174            e.printStackTrace();175        }176return "";177    }178179public String getString(int len) {180try {181             String strTemp = buff.getString(len, Charset.forName("GBK")182                    .newDecoder());183return strTemp;184         }catch (CharacterCodingException e) {185            e.printStackTrace();186            gets(len);187        }188return "";189    }190191public String getBcdString(int len) {192byte[] bytes =this.gets(len);193         StringBuilder bcd =new StringBuilder();194for (int m = 0; m < len; m++) {195             bcd.append(String.format("%02X", bytes[m]));196        }197return bcd.toString();198    }199200publicbyte[] array() {201int pos = buff.position();202byte[] data =newbyte[pos];203        buff.reset();204        buff.get(data);205return data;206    }207208publicstaticvoid main(String[] args) {209210         IoBuffer ib = IoBuffer.allocate(1024);211        ib.mark();212         ib.put((byte) 128);213        ib.reset();214// byte b = ib.get();215// int x = b& 0xff;216short x = ib.getUnsigned();217218short y = ib.getUnsigned(0);219220         System.out.println("" + x + "," + y);221    }222223 }

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

  1package com.hns.gps.gw.jt808.protocol;  2  3import com.hns.gps.gw.jt808.utils.Tools;  4import io.netty.buffer.ByteBuf;  5import io.netty.buffer.ByteBufAllocator;  6import io.netty.util.ReferenceCountUtil;  7import io.netty.util.ResourceLeakDetector;  8import org.apache.log4j.Logger;  9 10import java.io.UnsupportedEncodingException; 11import java.nio.charset.Charset; 12 13/** 14 *  ByteBuffer缓冲区,用Netty实现 15 * 16 *@author linys 17 * @create 2018-06-12 18 *@since 1.0.0 19*/ 20publicclass ByteBuffer { 21private Logger logger = Logger.getLogger(ByteBuffer.class); 22protected ByteBuf buff; 23 24public ByteBuffer() { 25         buff = ByteBufAllocator.DEFAULT.ioBuffer(1536); 26//为了找到ByteBuff没有被释放的原因 (上线关闭) 27        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); 28    } 29 30public ByteBuffer(byte[] bytes) { 31         buff = ByteBufAllocator.DEFAULT.ioBuffer(bytes.length); 32        buff.writeBytes(bytes); 33//为了找到ByteBuff没有被释放的原因 (上线关闭) 34        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); 35    } 36 37public ByteBuffer(byte[] bytes,int start,int length) { 38         buff = ByteBufAllocator.DEFAULT.ioBuffer(length); 39        buff.writeBytes(bytes, start, length); 40//为了找到ByteBuff没有被释放的原因 (上线关闭) 41        ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); 42    } 43 44publicvoid clear() { 45        buff.clear(); 46        buff.markWriterIndex(); 47        buff.markReaderIndex(); 48    } 49 50publicvoid put(byte a) { 51        buff.writeByte(a); 52    } 53 54publicvoid put(long a) { 55        buff.writeLong(a); 56    } 57 58publicvoid put(short a) { 59        buff.writeShort(a); 60    } 61 62publicvoid put(byte[] a) { 63        buff.writeBytes(a); 64    } 65 66publicboolean hasRemain() { 67return buff.isReadable(); 68    } 69 70publicvoid put(int a) { 71        buff.writeInt(a); 72    } 73 74publicvoid put(String str) { 75// US-ASCII 76try { 77byte[] b = str.getBytes("gbk"); 78            buff.writeBytes(b); 79         }catch (UnsupportedEncodingException e) { 80            logger.error(e.getMessage(), e); 81        } 82    } 83 84public String getBcdString(int len) { 85byte[] bytes =this.gets(len); 86         StringBuilder bcd =new StringBuilder(); 87for (int m = 0; m < len; m++) { 88             bcd.append(String.format("%02X", bytes[m])); 89        } 90return bcd.toString(); 91    } 92 93publicvoid putBcd(String str,int length) { 94byte[] b = BcDToBytes(str, length); 95        buff.writeBytes(b); 96    } 97 98publicstaticbyte[] BcDToBytes(String bcd,int len) { 99         bcd = bcd ==null ? "" : bcd;100while (bcd.length() < len) {101             bcd = "0" + bcd;102        }103return Tools.HexString2Bytes(bcd);104    }105106publicstatic String BytesToBcd(byte[] bytes,int start,int len) {107         StringBuilder bcd =new StringBuilder();108for (int m = 0; m < len; m++) {109             bcd.append(String.format("%02X", bytes[start + m]));110        }111return bcd.toString();112    }113114publicvoid put(String str,int len) {115byte[] result =newbyte[len];116try {117byte[] b = str.getBytes("gbk");118             System.arraycopy(b,0, result,0, b.length);119for (int m = b.length; m < len; m++) {120                 result[m] = 0;//不够位补0121            }122            buff.writeBytes(result);123         }catch (UnsupportedEncodingException e) {124            logger.error(e.getMessage(), e);125        }126    }127128publicbyte get() {129return buff.readByte();130    }131132publicshort getShort() {133return buff.readShort();134    }135136publicint getInt() {137return buff.readInt();138    }139140publiclong getLong() {141return buff.readLong();142    }143144publicdouble getDouble() {145return buff.readDouble();146    }147148publicbyte[] gets(int len) {149byte[] data =newbyte[len];150        buff.readBytes(data);151return data;152    }153154// 将data字节型数据转换为0~255 (0xFF 即BYTE)。155publicshort getUnsignedByte() {156return buff.readUnsignedByte();157    }158159// 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。160publicint getUnsignedShort() {161return buff.readUnsignedShort();162    }163164publiclong getUnsignedInt() {165return buff.readUnsignedInt();166    }167168public String getString() {169return buff.toString(Charset.forName("GBK"));170    }171172public String getString(int len) {173return buff.toString(0, len, Charset.forName("GBK"));174    }175176/**177     * 转换成byte数组178     *@return179*/180publicbyte[] toByteArray() {181int pos = buff.writerIndex();182byte[] data =newbyte[pos];183        buff.readBytes(data);184//再次调用重新从头读185        buff.resetReaderIndex();186return data;187    }188189/**190     * 清空释放buff,在buff使用结束后调用191     *@return192*/193publicvoid release() {194this.clear();195//释放缓冲区内存196        ReferenceCountUtil.release(buff);197    }198199/**200     * 转换成byte数组并清空释放buff,在buff使用结束后调用201     *@return202*/203publicbyte[] toByteArrayAndRelease() {204int pos = buff.writerIndex();205byte[] data =newbyte[pos];206        buff.readBytes(data);207this.clear();208//释放缓冲区内存209        ReferenceCountUtil.release(buff);210return data;211    }212213214 }

总结:处理网络数据的项目中经常需要处理字节数据,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

转载于:https://www.cnblogs.com/lys_013/p/9176037.html

  • 作者:weixin_30426065
  • 原文链接:https://blog.csdn.net/weixin_30426065/article/details/95059328
    更新时间:2022年9月6日10:14:53 ,共 8628 字。