傳統的java自帶的socket每次創建鏈接都會創建一個新的線程。建立線程過度的浪費服務器系統資源。java
jdk1.5前沒有NIO時經過僞異步方式解決,用線程池解決問題。緩存
IO和NIO的本質區別:阻塞和非阻塞的區別服務器
阻塞:應用程序中獲取網絡數據的時候,若是網絡傳輸數據很慢,那麼程序就一直等着,直到傳輸完畢爲止。網絡
非阻塞:應用程序直接能夠獲取已經準備好的數據,無需等待。異步
BIO爲同步阻塞形式,NIO爲異步非阻塞形式。NIO並無實現異步,中jdk1.7以後升級了NIO庫包。socket
同步和異步:同步和異步通常是面向操做系統與應用程序對IO操做的層面上來區別的。ide
同步時,應用程序會直接參與IO操做,而且咱們的應用程序會直接阻塞到某個方法上,直到數據準備就緒;或者採起輪詢的策略實時檢查數據的就緒狀態,若是就緒則獲取數據。ui
異步時,則全部的IO讀寫操做交給操做系統處理,與咱們的應用程序沒有直接關係,咱們的程序不關心IO讀寫,當操做系統完成了IO讀寫操做時,會給咱們應用程序發通知,咱們的應用程序直接拿走數據便可。操作系統
同步說的是server服務器端端執行方式。線程
阻塞說的是具體技術,接受數據的方式、狀態(IO,NIO)
AIO
Asynchronous Input/Output異步輸入/輸出是任何特殊輸入/輸出流
異步輸入/輸出是任何特殊輸入/輸出流(同步和異步輸入/輸出)兩個基本操做模式之一。在異步模式中,天然的輸入/輸出事務沒必要須和一個程序的輸入/輸出狀態同步或互鎖。例如,一個用戶或一個打字員應該被容許將信息提早輸入系統中來執行可以使用它們的讀狀態。每一個讀狀態的執行僅僅將下一個等待信息從一個輸入緩衝器中去除。這個異步輸入的例子相似於已經用於唱片、磁帶等中的緩衝提早讀方案。
Netty
netty實現通訊:
1 建立兩個NIO線程組,一個專門用於網絡事件處理(接受客戶端的鏈接),另外一個則進行網絡通訊編寫。
2 建立一個ServerBootstrap對象,配置netty的一系列參數,例如接受傳出數據的緩存大小等等。
3 建立一個世紀處理數據的類ChannelInitializer,進行初始化的準備工做,好比設置接受傳出數據的字符集、格式、已經實際處理數據的接口。
4 綁定端口,執行同步阻塞方法等待服務器端啓動便可。
示例:http://ifeve.com/netty5-user-guide/ 翻譯很差,可是例子比較簡單全面。
TCP粘包拆包問題
TCP是一個流協議。所謂流就是沒有界限的遺傳數據。你們能夠想象爲若是河水就比如數據,他們是連成一片的,沒有分界線。TCP底層並不瞭解上層的業務數據具體的含義,它會根據TCP緩衝區的實際狀況進行報的劃分,也就是說,在業務上咱們一個完整的報可能會被TCP分紅多個包進行發送,也可能把多個小包封裝成一個大的數據包發送出去,這就是所謂的TCP拆包粘包問題。
分析TCP粘包拆包問題產生緣由:
1應用程序write寫入的字節大小大於套接口發送緩衝區的大小。
2進行MSS大小的TCP分段。
3以太網幀的payload大雨MTU進行IP分片。
三種方案:
1消息定長,例如每一個報文的大小固定爲200個字節,若是不夠,空位補空格。
2在包尾部增長特殊字符進行分割。
3將消息分爲消息頭和消息體,在消息頭中包含消息總長度的字段,而後進行業務邏輯的處理。
netty中解決方法:
1 分隔符類 DelimiterBasedFrameDecoder(自定義分隔符)
2FixedLengthFrameDecoder(定長)