• Mina的IoBuffer改造成Netty的ByteBuff


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

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

      1 package com.hns.gps.gw.jt808.protocol;
      2 
      3 import com.hns.gps.gw.jt808.utils.Tools;
      4 import org.apache.log4j.Logger;
      5 import org.apache.mina.core.buffer.IoBuffer;
      6 
      7 import java.nio.charset.CharacterCodingException;
      8 import java.nio.charset.Charset;
      9 
     10 public class MyBuffer {
     11     private Logger logger = Logger.getLogger(MyBuffer.class);
     12     IoBuffer buff;
     13 
     14     public MyBuffer() {
     15         buff.setUseDirectBuffer(false);
     16         buff = IoBuffer.allocate(1536);
     17         buff.mark();
     18     }
     19 
     20     public MyBuffer(int len) {
     21         buff.setUseDirectBuffer(false);
     22         buff = IoBuffer.allocate(len);
     23         buff.mark();
     24     }
     25 
     26     public MyBuffer(byte[] bytes) {
     27         if (bytes.length > 1024)
     28             buff = IoBuffer.allocate(bytes.length + 100);
     29         else
     30             buff = IoBuffer.allocate(1024);
     31         buff.mark();
     32         buff.put(bytes);
     33         buff.limit(bytes.length);
     34         buff.reset();
     35     }
     36     public 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 
     45     public void clear() {
     46         buff.clear();
     47         buff.mark();
     48     }
     49 
     50     public void put(byte a) {
     51         buff.put(a);
     52     }
     53 
     54     public void put(long a)
     55     {
     56         buff.putLong(a);
     57     }
     58 
     59     public void put(short a) {
     60         buff.putShort(a);
     61     }
     62 
     63     public void put(byte[] a) {
     64         buff.put(a);
     65     }
     66 
     67     public boolean hasRemain() {
     68         return buff.remaining() > 0;
     69     }
     70 
     71     public void put(int a) {
     72         buff.putInt(a);
     73     }
     74 
     75     public void putShort(int a) {
     76         buff.putShort((short) a);
     77     }
     78 
     79     public void put(String str) {
     80         // US-ASCII
     81 
     82         try {
     83             byte[] b = str.getBytes("gbk");
     84             buff.put(b);
     85 
     86         } catch (Exception e) {
     87         //    logger.error(e.getMessage(), e);
     88         }
     89     }
     90 
     91     public void putBcd(String str, int length)
     92     {
     93         byte[] b = BcDToBytes(str,length);
     94         buff.put(b);
     95     }
     96 
     97 
     98     public static String BytesToBcd(byte[] bytes, int start, int len) {
     99         StringBuilder bcd = new StringBuilder();
    100         for (int m = 0; m < len; m++) {
    101             bcd.append(String.format("%02X", bytes[start + m]));
    102         }
    103         return bcd.toString();
    104     }
    105 
    106     public static byte[] BcDToBytes(String bcd, int len) {
    107         bcd = bcd == null ? "" : bcd;
    108         while (bcd.length() < len) {
    109             bcd = "0" + bcd;
    110         }
    111         return Tools.HexString2Bytes(bcd);
    112     }
    113 
    114     public void put(String str, int len) {
    115         byte[] result = new byte[len];
    116         try {
    117             byte[] b = str.getBytes("gbk");
    118 
    119             System.arraycopy(b, 0, result, 0, b.length);
    120 
    121             for (int m = b.length; m < len; m++) {
    122                 result[m] = 0;
    123             }
    124             buff.put(result);
    125 
    126         } catch (Exception e) {
    127             //logger.error(e.getMessage(), e);
    128         }
    129     }
    130 
    131     public byte get() {
    132         return buff.get();
    133     }
    134 
    135     public byte[] gets(int len) {
    136         byte[] data = new byte[len];
    137         buff.get(data);
    138         return data;
    139     }
    140 
    141     public int getInt() {
    142         return buff.getInt();
    143     }
    144 
    145     public short getShort() {
    146         return buff.getShort();
    147     }
    148 
    149     public long getLong() {
    150         return buff.getLong();
    151     }
    152 
    153     // 将data字节型数据转换为0~65535 (0xFFFF 即 WORD)。
    154     public int getUnsignedShort() {
    155         short t = buff.getShort();
    156         return t & 0xffff;
    157     }
    158 
    159     // 将data字节型数据转换为0~255 (0xFF 即BYTE)。
    160     public int getUnsignedByte() {
    161         return buff.get() & 0x0FF;
    162     }
    163 
    164     public long getUnsignedInt() {
    165         return buff.getInt() & 0x0FFFFFFFF;
    166     }
    167 
    168     public String getString() {
    169         try {
    170             String strTemp = buff
    171                     .getString(Charset.forName("GBK").newDecoder());
    172             return strTemp;
    173         } catch (CharacterCodingException e) {
    174             e.printStackTrace();
    175         }
    176         return "";
    177     }
    178 
    179     public String getString(int len) {
    180         try {
    181             String strTemp = buff.getString(len, Charset.forName("GBK")
    182                     .newDecoder());
    183             return strTemp;
    184         } catch (CharacterCodingException e) {
    185             e.printStackTrace();
    186             gets(len);
    187         }
    188         return "";
    189     }
    190 
    191     public String getBcdString(int len) {
    192         byte[] bytes = this.gets(len);
    193         StringBuilder bcd = new StringBuilder();
    194         for (int m = 0; m < len; m++) {
    195             bcd.append(String.format("%02X", bytes[m]));
    196         }
    197         return bcd.toString();
    198     }
    199 
    200     public byte[] array() {
    201         int pos = buff.position();
    202         byte[] data = new byte[pos];
    203         buff.reset();
    204         buff.get(data);
    205         return data;
    206     }
    207 
    208     public static void main(String[] args) {
    209 
    210         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;
    216         short x = ib.getUnsigned();
    217 
    218         short y = ib.getUnsigned(0);
    219 
    220         System.out.println("" + x + "," + y);
    221     }
    222 
    223 }

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

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

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

  • 相关阅读:
    W phase 学习
    有限破裂矩张量的发展历史
    Capjoint
    JavaScript之Function类型
    ThreadLocal学习资料
    Shiro学习资料
    jstl学习资料
    分页框架pager-taglib学习笔记
    MyBatis3学习笔记(曹锋老师版)
    关于处理日期格式化问题遇到的一个坑
  • 原文地址:https://www.cnblogs.com/lys_013/p/9176037.html
Copyright © 2020-2023  润新知