1. 程式人生 > >netty基礎入門(channel理解)

netty基礎入門(channel理解)

備註:本文的分析基於netty 4.0.9final版本,僅對Nio進行分析,因為本人對Socket程式設計比較感興趣。

1、channel總體機構圖

nio channel的總體結構圖如下:

2、關鍵類和介面分析

2.1  基於NioServerSocketChannel進行分析

1)Channel

Channel是頂層介面,繼承了AttributeMap, ChannelOutboundInvoker, ChannelPropertyAccess, Comparable<Channel>,它作為一個具體IO能力的元件提供給開發者,包括read, write, connect, and bind等操作。另外還提供了Channel配置的功能,以及獲取Channel所在的eventloop的功能。

2)AbstractChannel

AbstractChannel實現Channel介面,關鍵程式碼如下:

  1. privatefinal Channel parent;   
  2. privatefinallong hashCode = ThreadLocalRandom.current().nextLong();  
  3. privatefinal Unsafe unsafe;  
  4. privatefinal DefaultChannelPipeline pipeline;  
  5. privatefinal ChannelFuture succeededFuture = 
    new SucceededChannelFuture(thisnull);  
  6. privatefinal VoidChannelPromise voidPromise = new VoidChannelPromise(thistrue);  
  7. privatefinal VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(thisfalse);  
  8. privatefinal CloseFuture closeFuture = new CloseFuture(this);  
  9. privatevolatile
     SocketAddress localAddress;  
  10. privatevolatile SocketAddress remoteAddress;  
  11. privatevolatile EventLoop eventLoop;  
  12. privatevolatileboolean registered;  
  13. /** Cache for the string representation of this channel */
  14. privateboolean strValActive;  
  15. private String strVal;<pre name="code"class="java">    /** 
  16.  * Creates a new instance. 
  17.  * 
  18.  * @param parent 
  19.  *        the parent of this channel. {@code null} if there's no parent. 
  20.  */
  21. protected AbstractChannel(Channel parent) {  
  22.     this.parent = parent;  
  23.     unsafe = newUnsafe();  
  24.     pipeline = new DefaultChannelPipeline(this);  
  25. }  
比較重要的物件是pipeline和unsafe,它們提供對read,write,bind等操作的具體實現。

3)AbstractNioChannel

AbstractNioChannel繼承AbstractChannel,從這個類開始涉及到JDK的socket,參考如下關鍵程式碼:

  1. privatefinal SelectableChannel ch;  
  2.     protectedfinalint readInterestOp;  
  3.     privatevolatile SelectionKey selectionKey;  
  4.     privatevolatileboolean inputShutdown;  
  5. <pre name="code"class="java">    @Override
  6.     protectedvoid doRegister() throws Exception {  
  7.         boolean selected = false;  
  8.         for (;;) {  
  9.             try {  
  10.                 selectionKey = javaChannel().register(eventLoop().selector, 0this);  
  11.                 return;  
  12.             } catch (CancelledKeyException e) {  
  13.                 if (!selected) {  
  14.                     // Force the Selector to select now as the "canceled" SelectionKey may still be
  15.                     // cached and not removed because no Select.select(..) operation was called yet.
  16.                     eventLoop().selectNow();  
  17.                     selected = true;  
  18.                 } else {  
  19.                     // We forced a select operation on the selector before but the SelectionKey is still cached
  20.                     // for whatever reason. JDK bug ?
  21.                     throw e;  
  22.                 }  
  23.             }  
  24.         }  
  25.     }  

  /** * Create a new instance * * @param parent the parent {@link Channel} by which this instance was created. May be {@code null} * @param ch the underlying {@link SelectableChannel} on which it operates * @param readInterestOp the ops to set to receive data from the {@link SelectableChannel} */ protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) { super(parent); this.ch = ch; this.readInterestOp = readInterestOp; try { ch.configureBlocking(false); } catch (IOException e) { try { ch.close(); } catch (IOException e2) { if (logger.isWarnEnabled()) { logger.warn( "Failed to close a partially initialized socket.", e2); } } throw new ChannelException("Failed to enter non-blocking mode.", e); } } 從上面的程式碼可以看出,這裡定義真正的Socket Channel(SelectableChannel),關心的事件,註冊後的key。將Socket設定為非阻塞,這是所有非同步IO的關鍵,也就是說不管多麼好的框架,底層基礎還是不會變,可見學好基礎的重要性啊,^_^。這裡重點要關注一下register函式,這個函式是將Channel和事件迴圈進行關聯的關鍵。每個事件迴圈都有一個自己的selector,channel實際上是註冊到了相應eventloop的selector中,這也是Nio Socket程式設計的基礎。

從這個類中已經可以看到netty的channel是如何和socket 的nio channel關聯的了,以及channel是如何和eventloop關聯的了。

4)AbstractNioMessageChannel

這個類繼承AbstractNioChannel,主要是提供了一個newUnsafe方法返回NioMessageUnsafe物件的例項(實現read方法)。另外還定義doReadMessages和doWriteMessage兩個抽象方法。

5)ServerSocketChannel和ServerChannel

這兩個介面主要是定義了一個config方法,以及獲取網路地址的方法。

6)NioServerSocketChannel

NioServerSocketChannel繼承AbstractNioMessageChannel,實現ServerSocketChannel,它是一個具體類,提供給開發者使用。

  1. /** 
  2.  * A {@link io.netty.channel.socket.ServerSocketChannel} implementation which uses 
  3.  * NIO selector based implementation to accept new connections. 
  4.  */
  5. publicclass NioServerSocketChannel extends AbstractNioMessageChannel  
  6.                              implements io.netty.channel.socket.ServerSocketChannel {  
  7.     privatestaticfinal ChannelMetadata METADATA = new ChannelMetadata(false);  
  8.     privatestaticfinal InternalLogger logger = InternalLoggerFactory.getInstance(NioServerSocketChannel.class);  
  9.     privatestatic ServerSocketChannel newSocket() {  
  10.         try {  
  11.             return ServerSocketChannel.open();  
  12.         } catch (IOException e) {  
  13.             thrownew ChannelException(  
  14.                     "Failed to open a server socket.", e);  
  15.         }  
  16.     }  
  17.     privatefinal ServerSocketChannelConfig config;  
  18.     /** 
  19.      * Create a new instance 
  20.      */
  21.     public NioServerSocketChannel() {  
  22.         super(null, newSocket(), SelectionKey.OP_ACCEPT);  
  23.         config = new DefaultServerSocketChannelConfig(this, javaChannel().socket());  
  24.     }  
  25.     @Override
  26.     protected ServerSocketChannel javaChannel() {  
  27.         return

    相關推薦

    netty基礎入門channel理解

    備註:本文的分析基於netty 4.0.9final版本,僅對Nio進行分析,因為本人對Socket程式設計比較感興趣。 1、channel總體機構圖 nio channel的總體結構圖如下: 2、關鍵類和介面分析 2.1  基於Nio

    Java基礎入門十一之基本數據包裝類以及簡單轉換

    數據包 intvalue nbsp 1.5 lse false 永遠 ring jdk 一、 基本數據類型包裝類 引用數據類型一般為基本數據類型首字母大寫,除了int 、char,其中int的引用數據類型類Integer,char的引用數據類型為Character 關

    Python基礎入門類Class

    例項化:建立一個類的例項,類的具體物件。 類(Class): 用來描述具有相同的屬性和方法的物件的集合。它定義了該集合中每個物件所共有的屬性和方法。 方法:類中定義的函式。 類變數:類變數在整個例項化的物件中是公用的。類變數定義在類中且在函式體之外。類變數通常不作為例項變數使用。 資料成員:類變數

    七天LLVM零基礎入門Linux版本------第一天

    開篇語: 學習LLVM的過程是一個漫長而艱鉅的過程,需要大量的時間和精力。不僅僅如此,開始的過程也不輕鬆。一個好的開始就是成功的一半。我結合了自己學習的過程,以及給別人推薦學習的過程,整理出了這個七天LLVM零基礎入門的系列部落格。主要的目標是讓沒有LLVM基礎的人,經過

    Linux平臺Makefile檔案的編寫基礎入門課堂作業

    原作者:超超boy連結:http://www.cnblogs.com/jycboy/p/5084402.html根據老師的要求,寫一個超簡單的makefile準備:準備三個檔案:file1.c, file2.c, file2.h       file1.c:1234567#i

    Apache Flink 零基礎入門十一Flink transformation

    前面講了常用的DataSource的用法,DataSource其實是把資料載入進來,載入進來之後就需要做Transformatio

    Apache Flink 零基礎入門十八Flink windows和Time操作

    Time型別 在Flink中常用的Time型別: 處理時間 攝取時間 事件時間 處理時間 是上圖

    c#基礎入門數據類型

    文字 直接 種類型 常用 log 數據類型 logs 基礎 cnblogs 字符類型 char ,存儲用‘’(英文單引號)括起來的一個單個字符。例如: char Size=‘大‘;//存儲大小 字符串類型 string ,存儲用“”(英文雙引號)括起來的一串字符,不限量

    c#基礎入門算術運算符++ --

    -1 clas num strong ron ack col line 操作符 運算符又名操作符是用於運算的符號,作用於一個或多個的操作數。(操作數:參與運算的數據。) 運算符++和-- ++,叫做自加運算符。比如今天22號,明年長了一天,用代碼寫出來是這樣: int

    PHP基礎入門【PHP函數基礎

    就是 進行 size 自定義 取地址 代碼 功能 sha 有一種 PHP基礎入門(二)——函數基礎 了解 PHP基礎入門詳解(一) 後,給大家分享一下PHP的函數基礎。 這部分主要講的就是: 函數的聲明與使用、PHP中變量的作用域、靜態變量、函數的參數傳遞、變量函數

    02-Linux基礎入門

    ... man sso term 創建文件系統 www. lease linux系統 結果 一、命令必須掌握的命令:man,touch,ls,mkdir,cp,rm,mv,echo,pwd,cat,alias,unalias,head,tail,tree,rmdir想拿到高

    03-Linux基礎入門-系統的基礎優化[對於使用虛擬機學習的學習者]

    技術分享 ifcfg-eth 特殊 ... selinux 排查 運行 版本 get 1、關閉SELinux功能①SELinux配置文件路徑 /etc/selinux/config ②查看SELinux狀態 getenforce ③關閉SELinux 方法一:常規方法→修

    08-Linux基礎入門-文件和目錄的屬性及權限之文件類型、文件擴展名及文件權限基礎

    ins tmp first 串口 .py 都是 公眾平臺 cond .com 一、Linux中的文件類型在Linux系統中,可以說一切(包括目錄、普通文件、設備文件等)皆為文件。文件類型包含有普通文件、目錄、字符設備文件、設備文件、符號鏈接文件、管道文件等等,當執行ls

    10-Linux基礎入門-文件和目錄的屬性及權限之用戶與組和時間戳基礎

    log 信息 p s center 新浪 shell 使用 自己的 用戶配置 一、概述Linux是一個多用戶、多任務的操作系統,對於Linux系統來說,由於角色不同,權限和所完成的任務也不同。用戶的角色是通過UID和GID識別的,用戶的UID就相當於我們的身份證一樣,用戶名

    11-Linux基礎入門-Linux的通配符

    cal echo 微信公眾平臺 當前 技術分享 vertical hub font not 一、概述Linux的通配符和正則表達式是不一樣的,因此代表的意義也是有較大區別的。通配符一般用於用戶命令行bash環境,而Linux正則表達式用於grep、sed、awk場景。符號代

    PHP基礎入門

    是否 比較 shuffle end 填充 eset arr () int 數組處理:compact()函數:可以把單個變量,多個變量甚至數組放在一個數組中.$example=array("a","b","c");$example2=compact("d","e","exam

    PHP基礎入門

    pos public enc 靜態變量 類型 對象共享 cname 創建 不用 PHP的面向對象:聲明類: 訪問權限關鍵字 class 類名{成員屬性: 訪問權限關鍵字 $屬性名;成員方法: 訪問權限關鍵字 function 方法名(){}構造方法:function __c

    PHP基礎入門

    ipa arr 客戶 默認值 unset 他會 blog 不能 fine php現在很火的後臺開發語言,它融合了許多其他的語言,所以它的靈活性不用多說.話不多說,我們開始php的學習吧! 整數類型:$變量名=132;浮點類型:$變量名=1.32;字符串類型:$變量名="

    爬蟲基礎入門

    第三部分 tps 百度首頁 控制 set 協議 debug AD 主機 1 URL含義 URL的格式由三部分組成: ①第一部分是協議(或稱為服務方式)。 ②第二部分是存有該資源的主機IP地址(有時也包括端口號)。 ③第三部分是主機資源的具體地址,如目錄和文件名等。 2 分

    canvas基礎入門繪制線條、三角形、七巧板

    java i++ rip BE lin scrip 瀏覽器 返回 函數 復雜的內容都是有簡單的線條結合而成的,想要繪制出復雜好看的內容先從畫直線開始 canvas繪制直線先認識幾個函數 beginPath();開始一條路徑,或重置當前的路徑 moveTo(x,y);用於規定