网上有很多关于pos机解码教程,ByteBuffer的基本使用的知识,也有很多人为大家解答关于pos机解码教程的问题,今天pos机之家(www.poszjia.com)为大家整理了关于这方面的知识,让我们一起来看下吧!
本文目录一览:
1、pos机解码教程
pos机解码教程
一 、byteBuffer的基本使用
ByteBuffer 正确的使用姿势:
1 创建ByteBuffer对象: ByteBuffer buffer = ByteBuffer.allocate(10); 一般通过这个allocate()方法来分配
2 向buffer写入数据,调用channel.read(buffer)方法
3 调用flip()方法,切换到读取模式
4 从buffer中读取数据,buffer.get()
5 调用clear()或者compact()方法切换到写模式
6 重复2-5步
实例 :
用FileChannel读取test.txt文件到ByteBuffer,然后输出,test.txt内容为: 12345678fdsfds
/** * @program: isc-study * @description: * @author: wangjinwei * @create: 2021-09-26 09:17 **/public class ByteBufferTest { public static void main(String[] args) { //用FileChannel 来读取文件 try (RandomAccessFile file = new RandomAccessFile("E:\\\est.txt", "rw")) { FileChannel channel = file.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(10); while (true) { int len = channel.read(buffer); //读完了 if (len == -1) { break; } //切换到读取模式 buffer.flip(); while (buffer.hasRemaining()) { System.out.println((char) buffer.get()); } //清空到写模式 buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } }}
扩展总结:
1 这里有个问题 NIO的优势在非阻塞,那么这里 FileChannel可以设置为非阻塞模式么?
答案:当然不可以,FileChannel这个类继承了AbstractInterruptibleChannel抽象类,并没有继承SelectableChannel设置为阻塞模式的方法在SelectableChannel类里。
2 ByteBuffer.allocate(10)返回的是HeapByteBuffer 也就是说是堆内存,堆内存读写效率较低,存入的对象是受jvm GC管理
ByteBuffer.allocateDirect(10)返回直接内存,直接内存效率高,存的对象不受gc管理,当buffer对象被回收时,会执行释放的方法
二、ByteBuffer的分散聚集
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
还是以test.txt为例,读取时候使用多个buffer
public static void bufferTest2() { try (RandomAccessFile file = new RandomAccessFile("E:\\\est.txt", "rw")) { FileChannel channel = file.getChannel(); ByteBuffer buf1 = ByteBuffer.allocate(2); ByteBuffer buf2 = ByteBuffer.allocate(2); ByteBuffer[] bufs = {buf1, buf2}; while (true) { //分散读取 long len = channel.read(bufs); //读完了 if (len == -1) { break; } for (ByteBuffer buffer : bufs) { buffer.flip(); while (buffer.hasRemaining()) { System.out.println((char) buffer.get()); } //清空到写模式 buffer.clear(); } } } catch (IOException e) { e.printStackTrace(); }}
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
public static void bufferTest3() { try (RandomAccessFile file = new RandomAccessFile("E:\\\est.txt", "rw"); RandomAccessFile file2 = new RandomAccessFile("E:\\\est2.txt", "rw")) { FileChannel channel = file.getChannel(); FileChannel channel2 = file2.getChannel(); ByteBuffer buf1 = ByteBuffer.allocate(2); ByteBuffer buf2 = ByteBuffer.allocate(2); ByteBuffer[] bufs = {buf1, buf2}; while (true) { //分散读取 long len = channel.read(bufs); //读完了 if (len == -1) { break; } for (ByteBuffer buffer : bufs) { buffer.flip(); } //聚集写入 channel2.write(bufs); for (ByteBuffer buffer : bufs) { buffer.clear(); } } } catch (IOException e) { e.printStackTrace(); }}
总结:scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,
你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理消息头和消息体。这个分散/聚集读取,主要
学习的这个思想,本身用途不是很大
三、ByteBuffer 的拆包粘包
TCP传输数据时候 将多个发往接收端的包,为了更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,
合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了。
比如要发送下面3行字符
Hello,world\I'm zhangsan\How are you?\
变成了下面的两个 byteBuffer (粘包,半包)
Hello,world\I'm zhangsan\How are you?\
发生拆包粘包的场景:
1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
2.应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。
3.进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。
4.接收方法不及时读取套接字缓冲区数据,这将发生粘包。
所以发送端,接收端在接受数据时要做一些特殊处理 比如 数据之间使用 其他特殊符号进行分隔,本例中使用\
public static void bufferTest4() { ByteBuffer source = ByteBuffer.allocate(32); // 11 24 source.put("Hello,world\I'm zhangsan\Ho".getBytes()); split(source); source.put("w are you?\haha!\".getBytes()); split(source);} public static void split(ByteBuffer source) { source.flip(); int oldLimit = source.limit(); for (int i = 0; i < oldLimit; i++) { if (source.get(i) == '\') { System.out.println(i); ByteBuffer target = ByteBuffer.allocate(i + 1 - source.position()); // 0 ~ limit source.limit(i + 1); //这里会修改source的pos值 只会读取limit-position长度的字节 target.put(source); //打印buffer printBuffer(target); //为了给target赋值,上面修改了source的limit 这里把源buffer的limit设置回去, source.limit(oldLimit); } } source.compact();} public static void printBuffer(ByteBuffer buffer) { buffer.flip(); System.out.println(new String(buffer.array(),0,buffer.limit())); //清空到写模式 buffer.clear();} public static void main(String[] args) { bufferTest4();}
总结:这里只需要了解就可以了,netty提供了强大的编解码工具
以上就是关于pos机解码教程,ByteBuffer的基本使用的知识,后面我们会继续为大家整理关于pos机解码教程的知识,希望能够帮助到大家!
