日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

NIO 之 Channel实现原理

發布時間:2024/9/30 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NIO 之 Channel实现原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關文章

IO、NIO、AIO 內部原理分析
NIO 之 Selector實現原理
NIO 之 ByteBuffer實現原理

NIO概述

Java NIO 由以下幾個核心部分組成:

  • Channels
  • Buffers
  • Selectors

在傳統IO中,流是基于字節的方式進行讀寫的。
在NIO中,使用通道(Channel)基于緩沖區數據塊的讀寫。

Channel 和 IO 流的區別

Java NIO的通道類似IO中的流,但又有些不同:

  • 既可以從通道中讀取數據,又可以寫數據到通道。但流的讀寫通常是單向的。
  • 通道可以異步地讀寫。
  • 通道中的數據總是要先讀到一個Buffer,或者總是要從一個Buffer中寫入。
  • Channel 實現類

    下面是JAVA NIO中的一些主要Channel的實現:

  • FileChannel
    FileChannel 從文件中讀寫數據。
  • DatagramChannel
    DatagramChannel 能通過UDP讀寫網絡中的數據。
  • SocketChannel
    SocketChannel 能通過TCP讀寫網絡中的數據。
  • ServerSocketChannel
    ServerSocketChannel可以監聽新進來的TCP連接,像Web服務器那樣。對每一個新進來的連接都會創建一個SocketChannel。
  • FileChannel 是基于文件的Channel。
    DatagramChannel、SocketChannel、ServerSocketChannel 都是基于網絡流的Channel。

    下面我們主要介紹關于基于網絡流的SocketChannel 和 ServerSocketChannel 。

    register 方法

    基于網絡流的Channel中提供了register方法。
    使用示例:

    channel.register(selector, Selectionkey.OP_READ, ByteBuffer.allocate(64));

    代碼的寫法感覺是要將selector對象注冊到channel中。其實正好相反,應該是將channel注冊到selector中。
    下面通過代碼分析:
    ![將channel 注冊到 selector 中]

    1.首先判斷 selector 中是否已經注冊此 channel ,如果注冊過就更新注冊的事件和attach附件信息。
    2. 如果 selector 沒有注冊過 channel ,則將 channel 注冊到 selector 中。

    configureBlocking 方法

    public final SelectableChannel configureBlocking(boolean block)

    Channel 默認使用阻塞模式,通過 configureBlocking 方法可以將該 Channel 設置成非阻塞模式。

    //設置成非阻塞模式 channel.configureBlocking(false);

    ServerSocketChannel

    ServerSocketChannel只支持入站連接請求。不提供讀取、寫入數據功能。

    accept 方法

    public abstract SocketChannel accept()

    accept()可以在阻塞或非阻塞模式下操作。

    • 阻塞模式
      accept()方法等待入站連接。然后它接受一個連接,并返回到遠程客戶端的一個SocketChannel。在建立連接前你無法做任何操作。

    示例:

    public static void blockMode(){try {ServerSocketChannel serverChannel = ServerSocketChannel.open();//綁定要監控的端口serverChannel.bind(new InetSocketAddress(9000));//獲取入站請求socketChannelSocketChannel clientChannel = serverChannel.accept();...} catch (Exception e) {} }
    • 非阻塞模式
      如果沒有入站連接,accept()返回null。非阻塞模式一般和Selector結合使用。

    示例:

    public static void nonBlockMode(){try {//創建一個selectorSelector selector = Selector.open();//創建一個ServerSocketChannelServerSocketChannel serverChannel = ServerSocketChannel.open();//設置成非阻塞模式serverChannel.configureBlocking(false);//綁定要監控的端口serverChannel.bind(new InetSocketAddress(9000));//接受入站請求serverChannel.accept();//將 serverChannel 注冊到 selector 上serverChannel.register(selector, SelectionKey.OP_READ);} catch (Exception e) {} }

    SocketChannel

    SocketChannel 類可以讀寫TCP Socket。數據必須編碼到ByteBuffer對象中來完成讀寫。

    open 方法

  • public static SocketChannel open()
    創建一個SocketChannel,但不連接(沒有指定目標ip和port),如果想使用非阻塞模式則使用該方法創建SocketChannel對象。
  • 示例:

    public static void nonSocketChannel() throws Exception {SocketChannel client = SocketChannel.open();client.configureBlocking(false);client.connet(new InetSocketAddress("192.168.1.10", 9000)); }
  • public static SocketChannel open(SocketAddress remote)
    構造SocketChannel 對象,并使用阻塞模式連接目標地址。
  • connect 方法

    public abstract boolean connect(SocketAddress remote)

    非阻塞模式下,如果要連接遠程服務器必須使用 connect 方法進行連接。

    finishConnect 方法

    public abstract boolean finishConnect()

    阻塞模式:直接返回true,因為在構造SocketChannel的時候已經建立連接了。
    非阻塞模式下:必須調用此方法來判斷該方法是否已經建立網絡連接,只有建立網絡連接后才能進行讀寫操作。

    判斷網絡連接狀態

    public abstract boolean isConnected()
    判斷是否已經連接。
    public abstract boolean isConnectionPending()
    判斷連接是否正在連接狀態

    read 方法

    • public int read(ByteBuffer buf)
      將 SocketChannel 中的數據讀入填充到 buf 中
    • public final long read(ByteBuffer[] dsts)
      將 SocketChannel 中的數據讀入填充到 dsts[] 數組。按照數組順序進行填充。
    • public long read(ByteBuffer[] dsts, int offset, int length)
      將 SocketChannel 中的數據填充到 dsts[] 數組中,從第數組中的offset坐標開始填充,填充 length 個Bytebuffer。

    write 方法

    • public int write(ByteBuffer src)
      將 buf 中的數據寫入到 SocketChannel 中
    • public final long write(ByteBuffer[] srcs)
      將 srcs[] 數組中的數據寫入到 SocketChannel 中,按照數組順序一個一個寫入。
    • public long write(ByteBuffer[] srcs, int offset, int length)
      將 srcs[] 數組中的數據寫入到 SocketChannel 中,從數組中 offset 坐標開始,寫入length個ByteBuffer對象。

    本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
    點擊這里快速進入簡書

    GIT地址:http://git.oschina.net/brucekankan/
    點擊這里快速進入GIT

    總結

    以上是生活随笔為你收集整理的NIO 之 Channel实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。