pos機(jī)解碼教程,ByteBuffer的基本使用

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

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

本文目錄一覽:

1、pos機(jī)解碼教程

pos機(jī)解碼教程

一 、byteBuffer的基本使用

ByteBuffer 正確的使用姿勢(shì):

1 創(chuàng)建ByteBuffer對(duì)象: ByteBuffer buffer = ByteBuffer.allocate(10); 一般通過(guò)這個(gè)allocate()方法來(lái)分配

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

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

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

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

6 重復(fù)2-5步

實(shí)例 :

用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 來(lái)讀取文件 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()); } //清空到寫(xiě)模式 buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } }}

擴(kuò)展總結(jié):

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

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

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

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

二、ByteBuffer的分散聚集

分散(scatter)從Channel中讀取是指在讀操作時(shí)將讀取的數(shù)據(jù)寫(xiě)入多個(gè)buffer中。因此,Channel將從Channel中讀取的數(shù)據(jù)“分散(scatter)”到多個(gè)Buffer中。

還是以test.txt為例,讀取時(shí)候使用多個(gè)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()); } //清空到寫(xiě)模式 buffer.clear(); } } } catch (IOException e) { e.printStackTrace(); }}

聚集(gather)寫(xiě)入Channel是指在寫(xiě)操作時(shí)將多個(gè)buffer的數(shù)據(jù)寫(xiě)入同一個(gè)Channel,因此,Channel 將多個(gè)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(); } //聚集寫(xiě)入 channel2.write(bufs); for (ByteBuffer buffer : bufs) { buffer.clear(); } } } catch (IOException e) { e.printStackTrace(); }}

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

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

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

三、ByteBuffer 的拆包粘包

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

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

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

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

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

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

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

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

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

3.進(jìn)行MSS(最大報(bào)文長(zhǎng)度)大小的TCP分段,當(dāng)TCP報(bào)文長(zhǎng)度-TCP頭部長(zhǎng)度>MSS的時(shí)候?qū)l(fā)生拆包。

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

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

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); //這里會(huì)修改source的pos值 只會(huì)讀取limit-position長(zhǎng)度的字節(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())); //清空到寫(xiě)模式 buffer.clear();} public static void main(String[] args) { bufferTest4();}

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

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

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

你可能會(huì)喜歡:

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