Java ByteBuffer用法总结

作者在使用SocketChannel进行网络编程时,因ByteBuffer使用不当遇到问题。总结了ByteBuffer几个标志(position、limit等)含义,操作(flip、clear等)影响,以及读写时标志变化。还介绍了SocketChannel非阻塞异步读取数据流程,以及处理数据包的方法,提到rewind可重复读数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近用SocketChannel进行网络编程比较多,中间也遇到了几个问题,出现的bug也主要来自于对于ByteBuffer的使用不当。现在终于调通了,对ByteBuffer及Socket网络编程也有了更深的认识,特此总结一下。

对于ByteBuffer主要需要注意的是几个标志的含义:position,limit,capability,mark.几个操作的影响:flip(),clear(),rewind().还有就是在读取或者写入时,标志的变化,比如get()方法导致position加1.

SocketChannel采用的是非阻塞异步读取流数据,在读取的时候,通常是

<ol class="linenums" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px 0px 0px 26px; vertical-align: baseline; list-style-position: initial;"><li value="1" class="L0" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">clear</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">();</span></li><li class="L1" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">SocketChannel</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">read</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">(</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">);</span></li></ol>

如果流中有数据,就会把数据从position开始读到ByteBuffer中,在读取之前ByteBuffer的clear操作会把position置为0,limit置为capability,也就是相当于清空了之前的内容,但是ByteBuffer中数组的内容在read之前是没有改变的.

read之后,通常就是开始从ByteBuffer中提取读到的数据,如果你的数据是以自己定义的数据包的格式进行发送的,那你还需要判断是否读到了数据包的结尾,因为对流数据本身来说是没有结尾这一说的。在提取数据之前,要先把position放到开始读取时的位置,把limit放到当前位置,所以要flip一下,表示从position到limit的位置都是需要的数据。

<ol class="linenums" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px 0px 0px 26px; vertical-align: baseline; list-style-position: initial;"><li value="1" class="L0" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">flip</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">();</span></li><li class="L1" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">while</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">(</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">hasRemaining</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">()){</span></li><li class="L2" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">byte</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);"> c</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">=</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">get</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">();</span></li><li class="L3" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">if</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);"> </span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">(</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">b </span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">==</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);"> PACKAGE_END</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">)</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);"> </span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">{</span></li><li class="L4" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">		</span><span class="com" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(136, 0, 0);">//you can return the package here</span></li><li class="L5" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">}</span><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">else</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">{</span></li><li class="L6" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">		</span><span class="com" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(136, 0, 0);">//you can append the byte here.like StringBuilder.append().</span></li><li class="L7" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">}</span></li><li class="L8" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">}</span></li></ol>

这样以来也存在一个问题,当一次读到的ByteBuffer不包含完整的数据包或者包含多个数据包.那么就需要在下一次继续把这些包分拆出来.那么在读取数据的代码处就可以改为,这样就把之前读取到的未完整的包保留了下来:

<ol class="linenums" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px 0px 0px 26px; vertical-align: baseline; list-style-position: initial;"><li value="1" class="L0" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="kwd" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 136);">if</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">(!</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">hasRemaining</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">){</span></li><li class="L1" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">clear</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">();</span></li><li class="L2" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal;"><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">	</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">SocketChannel</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">.</span><span class="pln" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);">read</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">(</span><span class="typ" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 0, 102);">ByteBuffer</span><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">);</span></li><li class="L3" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; list-style-type: decimal; background-color: rgb(238, 238, 238);"><span class="pun" style="border: 0px; font-family: inherit; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; color: rgb(102, 102, 0);">}</span></li></ol>

另外一个可能会用到的操作就是ByteBuffer.rewind(),他会把position置为0,limit保持不变,可以用于重复读取一段数据.

ByteBuffer是nio中一个非常方便的工具.设计思想也非常值得借鉴.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值