一些基本概念
1 Socket
1) 同一個名詞Socket有多種不同意思。
2) 在計算機(jī)網(wǎng)絡(luò)知識體系中,運輸層的TCP(傳輸控制協(xié)議)把連接作為最基本的抽象腥光。TCP的連接有兩個端點懒构,被稱為Socket众羡,通過IP地址+端口號來區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信勋颖,實現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)嗦嗡。Client進(jìn)程和Server進(jìn)程之間是通過Socket讀寫數(shù)據(jù)進(jìn)行通信的。
3) JDK的java.net包下有兩個類:Socket
和ServerSocket
饭玲,在Client和Server建立連接成功后侥祭,兩端都會產(chǎn)生一個Socket實例,操作這個實例茄厘,完成所需的會話矮冬,而程序員就通過這些API進(jìn)行網(wǎng)絡(luò)編程。 Socket連接過程分為三個步驟:服務(wù)器監(jiān)聽次哈,客戶端請求胎署,連接確認(rèn)。需要注意的是窑滞,Socket自己并不是一種協(xié)議琼牧,而是對TCP/IP協(xié)議的抽象,并提供最基本的函數(shù)接口方便開發(fā)者調(diào)用哀卫。
2 Netty
Netty.io官網(wǎng)介紹:
Netty是一個異步非阻塞的事件驅(qū)動型的網(wǎng)絡(luò)應(yīng)用程序框架巨坊。滿足高性能協(xié)議服務(wù)器和客戶端的快速發(fā)展需求。
Netty是一個高性能此改、方便開發(fā)的NIO框架趾撵,使用它可以簡單快速地開發(fā)網(wǎng)絡(luò)應(yīng)用程序,比如客戶端和服務(wù)端的協(xié)議带斑。Netty大大簡化了網(wǎng)絡(luò)編程比如TCP和UDP的 Socket的開發(fā)鼓寺。
“快速和簡單”并不意味著應(yīng)用程序會有難維護(hù)和性能低的問題,Netty是一個精心設(shè)計的框架勋磕,它從FTP妈候、SMTP、HTTP挂滓、許多二進(jìn)制和基于文本的傳統(tǒng)協(xié)議實現(xiàn)中吸收了經(jīng)驗苦银,為我們提供了一個高開發(fā)效率、高性能赶站、穩(wěn)定幔虏、可伸縮的解決方案。
3 NIO
剛剛提到:
Netty是一個NIO框架贝椿。
理解NIO框架的基本概念有助于學(xué)習(xí)Netty提供給開發(fā)者使用的API想括。
NIO 是jdk1.4 里提供的新API,全稱即java new I/O烙博。Sun 官方標(biāo)榜的特性如下: 為所有的原始類型提供緩存(Buffer)支持瑟蜈。
首先我們來回憶一下Java的IO
- IO可以簡單理解為 數(shù)據(jù)流方向:程序→硬盤寫數(shù)據(jù)(Output)以及 硬盤→程序讀數(shù)據(jù)(Input)烟逊,同時Java IO是基于流(Stream)的,所有的API都繼承自
InputStream/OutputStream
铺根。意味著每次從流中讀一個或多個字節(jié)宪躯,直至讀取所有字節(jié),它們沒有被緩存在任何地方位迂。 - IO的過程是阻塞的访雪,也就是說當(dāng)一個線程調(diào)用read() 或 write()時,該線程被阻塞掂林,直到有一些數(shù)據(jù)被讀取臣缀,或數(shù)據(jù)完全寫入。該線程在此期間不能再干任何事情了党饮。
然后我們再來看NIO:
NIO包括三個核心:
- Channels
FileChannel肝陪、DatagramChannel、SocketChannel刑顺、ServerSocketChannel
這些通道涵蓋了UDP 和 TCP 網(wǎng)絡(luò)IO氯窍,以及文件IO。
Java NIO的通道類似流蹲堂,但又有些不同:
1)流只是在一個方向上移動(一個流必須是 InputStream 或者 OutputStream 的子類)狼讨,而通道可以用于讀、寫或者同時用于讀寫柒竞,是全雙工的政供。
2)通道可以異步地讀寫。
3)通道中的數(shù)據(jù)總是要先讀到一個Buffer朽基,或者總是要從一個Buffer中寫入布隔。
實際上Channel可以分為兩大類,分別是用于網(wǎng)絡(luò)讀寫的SelectableChannel
和用于文件操作的FileChannel
稼虎。
Netty中ServerSocketChannel和SocketChannel都是SelectableChannel的子類 衅檀。 - Buffers
所有數(shù)據(jù)都是用緩沖區(qū)進(jìn)行處理的。在讀取數(shù)據(jù)時霎俩,它是直接讀到緩沖區(qū)中哀军;在寫入數(shù)據(jù)時,它也是寫入到緩沖區(qū)中打却。任何時候訪問 NIO 中的數(shù)據(jù)杉适,我們都是通過緩沖區(qū)進(jìn)行讀寫操作。
緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù)柳击,然后可以從中讀取數(shù)據(jù)的內(nèi)存猿推。這塊內(nèi)存被包裝成NIO Buffer對象,并提供了一組方法捌肴,用來方便的訪問該塊內(nèi)存蹬叭。
NIO中Buffer的實現(xiàn)包括ByteBuffer毯侦、CharBuffer、DoubleBuffer
等等具垫,這些Buffer覆蓋了你能通過IO發(fā)送的基本數(shù)據(jù)類型:byte, short, int, long, float, double 和 char。
- Selectors
Selector(選擇器)是Java NIO中能夠檢測一到多個NIO通道试幽,并能夠知曉通道是否為諸如讀寫事件做好準(zhǔn)備的組件筝蚕。
Selector允許單線程處理多個 Channel。如果你的應(yīng)用打開了多個連接(通道)铺坞,但每個連接的流量都很低起宽,使用Selector就會很方便。例如济榨,在一個聊天服務(wù)器中坯沪。
Selector會不斷的輪詢注冊在其上的Channel,如果某個Channel上面有新的TCP連接接入擒滑、讀和寫事件腐晾,這個Channel就處于就緒狀態(tài),會被Selector輪詢出來丐一,然后通過SelectionKey可以獲取就緒Channel的集合進(jìn)行后續(xù)的IO操作藻糖。
所以,與IO相比库车,
- NIO是從緩沖區(qū)(Buffer)讀寫數(shù)據(jù)的巨柒,而不是面向流(Stream)。例如在讀取硬盤數(shù)據(jù)時柠衍,并不是僅從一個InputStream上逐字節(jié)讀取洋满,而是數(shù)據(jù)必須先讀入緩沖區(qū)再處理。
- NIO在一個線程從某通道發(fā)送請求讀取數(shù)據(jù)珍坊,并不會保持線程阻塞牺勾,所以直至數(shù)據(jù)變的可以讀取之前,該線程可以繼續(xù)做其他的事情垫蛆。 非阻塞寫也是如此禽最。一個線程請求寫入一些數(shù)據(jù)到某通道,但不需要等待它完全寫入袱饭,這個線程同時可以去做別的事情川无。 線程通常將非阻塞IO的空閑時間用于在其它通道上執(zhí)行IO操作,所以一個單獨的線程現(xiàn)在可以管理多個輸入和輸出通道(channel)虑乖。
最后
抱歉這是一篇搬運后排版出來的文章懦趋,花了點時間整理了下Netty框架相關(guān)的知識。尤其是NIO這一塊疹味,雖然網(wǎng)上的言論都是不建議直接基于JDK的NIO類庫進(jìn)行開發(fā)仅叫,幾乎都推薦使用Netty開發(fā)NIO服務(wù)端帜篇,但是了解NIO的一些核心概念,肯定有助于對Netty整個代碼模式以及API使用的學(xué)習(xí)诫咱。這兩天會再整理一下在Android客戶端開發(fā)中Netty的具體使用笙隙。