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

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

網上有很多關于pos機解碼教程,ByteBuffer的基本使用的知識,也有很多人為大家解答關于pos機解碼教程的問題,今天pos機之家(www.tonybus.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機解碼教程的知識,希望能夠幫助到大家!

轉發請帶上網址:http://www.tonybus.com/newsone/58793.html

你可能會喜歡:

版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 babsan@163.com 舉報,一經查實,本站將立刻刪除。