NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径
NIO之ByteBuffer與Channel
傳統(tǒng)IO:byte[] <= inputStream <= 文件 => outputStream => byte[] NIO:文件 => inputChannel <=> buffer <=> outputChannel => 文件文件 <= inputChannel <=> outputChannel => 文件- 文件復(fù)制, 并測(cè)試ByteBuffer常用API
position: 當(dāng)前指針位置; limit: 當(dāng)前內(nèi)容的最大位置(例如: buffer內(nèi)容為"hello", 容量為20, limit就是5); capacity: 最大容量
clear, flip源碼如下:
public final Buffer clear() {position = 0;limit = capacity;mark = -1;return this;}public final Buffer flip() {limit = position;position = 0;mark = -1;return this;}- DirectByteBuffer
ByteBuffer.allocate(1024) => HeapByteBuffer, 內(nèi)部使用的就是byte[], 底層源碼如下
HeapByteBuffer位于JVM堆空間, 當(dāng)使用HeapByteBuffer進(jìn)行內(nèi)容復(fù)制時(shí), 存在2個(gè)復(fù)制過程: 應(yīng)用程序 => 應(yīng)用程序緩沖區(qū) => 內(nèi)核緩沖區(qū) => 文件; 這種情況下, 2個(gè)復(fù)制過程存在一定的性能問題;
ByteBuffer.allocateDirect(1024) => DirectByteBuffer, DirectByteBuffer使用native方法創(chuàng)建數(shù)組, 數(shù)組不再位于JVM的Heap中, 而是位于內(nèi)核內(nèi)存中, 這樣就避免了一次數(shù)據(jù)拷貝(拷貝的原因在于JVM中數(shù)據(jù)的地址會(huì)改變, 在GC下): 應(yīng)用程序緩沖區(qū) -> 內(nèi)核緩沖區(qū); 所謂的零拷貝, 加快速度, C/C++開辟的數(shù)組空間都是位于內(nèi)核緩沖區(qū)
DirectByteBuffer底層源碼:
使用DirectByteBuffer進(jìn)行文件復(fù)制:
/*** 測(cè)試DirectByteBuffer* @author regotto*/ public class NioTest2 {public static void main(String[] args) throws Exception {FileChannel inputChannel = new FileInputStream("input.txt").getChannel();FileChannel outputChannel = new FileOutputStream("output.txt").getChannel();ByteBuffer buffer = ByteBuffer.allocateDirect(4);while(true){buffer.clear();int read = inputChannel.read(buffer);System.out.println("read: " + read);if (-1 == read){break;}buffer.flip();outputChannel.write(buffer);// buffer.flip();}inputChannel.close();outputChannel.close();}/*** 進(jìn)行文件復(fù)制*/public void test() throws Exception {FileChannel fisChannel = new FileInputStream("text1.txt").getChannel();FileChannel fosChannel = new FileOutputStream("text2.txt").getChannel();//transferTo與transferFrom效果一樣fisChannel.transferTo(0, fisChannel.size(), fosChannel);fisChannel.close();fosChannel.close();} }- 使用堆外內(nèi)存進(jìn)行文件內(nèi)容復(fù)制(使用塊內(nèi)存提高性能)
NIO之網(wǎng)絡(luò)IO
使用NIO進(jìn)行網(wǎng)絡(luò)非阻塞式編程, NIO編程模型圖:
NIO網(wǎng)絡(luò)編程結(jié)構(gòu)圖:
根據(jù)上面結(jié)構(gòu)圖編寫簡(jiǎn)單案例代碼:
NioServer
NioClient
/*** client*/ public class NioClient {public static void main(String[] args) throws IOException, InterruptedException {SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);if (!socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999))) {//連接服務(wù)端失敗, 使用finishConnect進(jìn)行連接, 此處finishConnect非阻塞while (!socketChannel.finishConnect()) {System.out.println("連接同時(shí), 干其他事情");TimeUnit.SECONDS.sleep(2);}}//return new HeapByteBuffer(capacity, capacity); // ByteBuffer.allocate(1024);//return new HeapByteBuffer(array, offset, length);ByteBuffer buffer = ByteBuffer.wrap("hello world".getBytes(StandardCharsets.UTF_8));socketChannel.write(buffer);//此處阻塞, 若關(guān)閉連接, server會(huì)拋出異常System.out.println("進(jìn)入睡眠");Thread.currentThread().join();} }Netty初窺門徑
- Netty模型:
- NioEventLoopGroup模型:
- ChannelPipeline模型:
- 簡(jiǎn)單入門案例:
NettyServer:
NettyServerHandler:
public class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf byteBuf = (ByteBuf) msg;System.out.println("客戶端發(fā)送的內(nèi)容: " + byteBuf.toString(CharsetUtil.UTF_8));}/*** 數(shù)據(jù)讀取完成* @param ctx Channel上下文對(duì)象* @throws Exception*/@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("就是沒錢", CharsetUtil.UTF_8));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {//出現(xiàn)異常, 直接關(guān)閉上下文對(duì)象ctx.close();} }NettyClient
/*** 客戶端*/ public class NettyClient {public static void main(String[] args) throws InterruptedException {EventLoopGroup workGroup = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap().group(workGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new NettyClientHandler());}});ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9999).sync();channelFuture.channel().closeFuture().sync();} }NettyClientHandler:
public class NettyClientHandler extends ChannelInboundHandlerAdapter {/*** 通道準(zhǔn)備就緒, 當(dāng)前已經(jīng)連接* @param ctx* @throws Exception*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("老板, 還錢吧".getBytes(CharsetUtil.UTF_8)));}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf byteBuf = (ByteBuf) msg;System.out.println(byteBuf.toString(CharsetUtil.UTF_8));} }總結(jié)
以上是生活随笔為你收集整理的NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑如何测网速_物联网卡的网速到底怎么样
- 下一篇: 流水灯c语言实验报告心得,嵌入式流水灯实