pos機解碼教程,ByteBuffer的基本使用

 新聞資訊2  |   2023-05-27 09:53  |  投稿人:pos機之家

網(wǎng)上有很多關(guān)于pos機解碼教程,ByteBuffer的基本使用的知識,也有很多人為大家解答關(guān)于pos機解碼教程的問題,今天pos機之家(m.afbey.com)為大家整理了關(guān)于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、pos機解碼教程

pos機解碼教程

一 、byteBuffer的基本使用

ByteBuffer 正確的使用姿勢:

1 創(chuàng)建ByteBuffer對象: ByteBuffer buffer = ByteBuffer.allocate(10); 一般通過這個allocate()方法來分配

2 向buffer寫入數(shù)據(jù),調(diào)用channel.read(buffer)方法

3 調(diào)用flip()方法,切換到讀取模式

4 從buffer中讀取數(shù)據(jù),buffer.get()

5 調(diào)用clear()或者compact()方法切換到寫模式

6 重復(fù)2-5步

實例 :

用FileChannel讀取test.txt文件到ByteBuffer,然后輸出,test.txt內(nèi)容為: 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(); } }}

擴展總結(jié):

1 這里有個問題 NIO的優(yōu)勢在非阻塞,那么這里 FileChannel可以設(shè)置為非阻塞模式么?

答案:當然不可以,F(xiàn)ileChannel這個類繼承了AbstractInterruptibleChannel抽象類,并沒有繼承SelectableChannel設(shè)置為阻塞模式的方法在SelectableChannel類里。

2 ByteBuffer.allocate(10)返回的是HeapByteBuffer 也就是說是堆內(nèi)存,堆內(nèi)存讀寫效率較低,存入的對象是受jvm GC管理

ByteBuffer.allocateDirect(10)返回直接內(nèi)存,直接內(nèi)存效率高,存的對象不受gc管理,當buffer對象被回收時,會執(zhí)行釋放的方法

二、ByteBuffer的分散聚集

分散(scatter)從Channel中讀取是指在讀操作時將讀取的數(shù)據(jù)寫入多個buffer中。因此,Channel將從Channel中讀取的數(shù)據(jù)“分散(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的數(shù)據(jù)寫入同一個Channel,因此,Channel 將多個Buffer中的數(shù)據(jù)“聚集(gather)”后發(fā)送到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(); }}

總結(jié):scatter / gather經(jīng)常用于需要將傳輸?shù)臄?shù)據(jù)分開處理的場合,例如傳輸一個由消息頭和消息體組成的消息,

你可能會將消息體和消息頭分散到不同的buffer中,這樣你可以方便的處理消息頭和消息體。這個分散/聚集讀取,主要

學(xué)習(xí)的這個思想,本身用途不是很大

三、ByteBuffer 的拆包粘包

TCP傳輸數(shù)據(jù)時候 將多個發(fā)往接收端的包,為了更有效的發(fā)到對方,使用了優(yōu)化方法(Nagle算法),將多次間隔較小且數(shù)據(jù)量小的數(shù)據(jù),

合并成一個大的數(shù)據(jù)塊,然后進行封包。這樣,接收端,就難于分辨出來了。

比如要發(fā)送下面3行字符

Hello,world\I'm zhangsan\How are you?\

變成了下面的兩個 byteBuffer (粘包,半包)

Hello,world\I'm zhangsan\How are you?\

發(fā)生拆包粘包的場景:

1. 應(yīng)用程序?qū)懭氲臄?shù)據(jù)大于套接字緩沖區(qū)大小,這將會發(fā)生拆包。

2.應(yīng)用程序?qū)懭霐?shù)據(jù)小于套接字緩沖區(qū)大小,網(wǎng)卡將應(yīng)用多次寫入的數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上,這將會發(fā)生粘包。

3.進行MSS(最大報文長度)大小的TCP分段,當TCP報文長度-TCP頭部長度>MSS的時候?qū)l(fā)生拆包。

4.接收方法不及時讀取套接字緩沖區(qū)數(shù)據(jù),這將發(fā)生粘包。

所以發(fā)送端,接收端在接受數(shù)據(jù)時要做一些特殊處理 比如 數(shù)據(jù)之間使用 其他特殊符號進行分隔,本例中使用\

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長度的字節(jié) target.put(source); //打印buffer printBuffer(target); //為了給target賦值,上面修改了source的limit 這里把源buffer的limit設(shè)置回去, 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();}

總結(jié):這里只需要了解就可以了,netty提供了強大的編解碼工具

以上就是關(guān)于pos機解碼教程,ByteBuffer的基本使用的知識,后面我們會繼續(xù)為大家整理關(guān)于pos機解碼教程的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://m.afbey.com/newsone/58793.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。