NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径
生活随笔
收集整理的這篇文章主要介紹了
NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
NIO之ByteBuffer與Channel
傳統IO:byte[] <= inputStream <= 文件 => outputStream => byte[] NIO:文件 => inputChannel <=> buffer <=> outputChannel => 文件文件 <= inputChannel <=> outputChannel => 文件- 文件復制, 并測試ByteBuffer常用API
position: 當前指針位置; limit: 當前內容的最大位置(例如: buffer內容為"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, 內部使用的就是byte[], 底層源碼如下
HeapByteBuffer位于JVM堆空間, 當使用HeapByteBuffer進行內容復制時, 存在2個復制過程: 應用程序 => 應用程序緩沖區 => 內核緩沖區 => 文件; 這種情況下, 2個復制過程存在一定的性能問題;
ByteBuffer.allocateDirect(1024) => DirectByteBuffer, DirectByteBuffer使用native方法創建數組, 數組不再位于JVM的Heap中, 而是位于內核內存中, 這樣就避免了一次數據拷貝(拷貝的原因在于JVM中數據的地址會改變, 在GC下): 應用程序緩沖區 -> 內核緩沖區; 所謂的零拷貝, 加快速度, C/C++開辟的數組空間都是位于內核緩沖區
DirectByteBuffer底層源碼:
使用DirectByteBuffer進行文件復制:
/*** 測試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();}/*** 進行文件復制*/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();} }- 使用堆外內存進行文件內容復制(使用塊內存提高性能)
NIO之網絡IO
使用NIO進行網絡非阻塞式編程, NIO編程模型圖:
NIO網絡編程結構圖:
根據上面結構圖編寫簡單案例代碼:
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))) {//連接服務端失敗, 使用finishConnect進行連接, 此處finishConnect非阻塞while (!socketChannel.finishConnect()) {System.out.println("連接同時, 干其他事情");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);//此處阻塞, 若關閉連接, server會拋出異常System.out.println("進入睡眠");Thread.currentThread().join();} }Netty初窺門徑
- Netty模型:
- NioEventLoopGroup模型:
- ChannelPipeline模型:
- 簡單入門案例:
NettyServer:
NettyServerHandler:
public class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf byteBuf = (ByteBuf) msg;System.out.println("客戶端發送的內容: " + byteBuf.toString(CharsetUtil.UTF_8));}/*** 數據讀取完成* @param ctx Channel上下文對象* @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 {//出現異常, 直接關閉上下文對象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 {/*** 通道準備就緒, 當前已經連接* @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));} }總結
以上是生活随笔為你收集整理的NIO之ByteBuffer_NIO之网络IO_与ChannelNetty初窥门径的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑如何测网速_物联网卡的网速到底怎么样
- 下一篇: Linux_ACL_su