netty學習筆記【不斷更新】

git 地址:https://github.com/chris1132/netty_lecture
2018-7-20
開始系統學習netty
完成服務端部分
https://blog.csdn.net/u010530712/article/details/82107187html

2018-7-22html5

實現客戶端和服務端基於tcp雙向通訊java

源碼 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/secondeexample
2018-7-24
一、netty自己不是按照servlet規則;
二、http是請求響應模式的無狀態的協議,對於netty是監聽tcp的端口號,對於他們底層來講還是serversocket;
三、對於springmvc程序來講,運行在jetty、Tomcat這些servlet容器上,這些容器保證鏈接關閉,對於netty,鏈接能夠本身控制如keepalive時間
python

2018-7-25git

一、netty對請求路由沒提供支持;github

二、netty完成socket相關開發;支持長鏈接開發;web

三、websocket實現客戶端與服務端的持續鏈接,可相互發消息。不須要封裝不必的消息,如http中的header;spring

2018-7-26
一、SimpleChannelInboundHandler<T> T泛型,要處理的消息的 Java 類型;
二、ChannelHandler,ChannelHandlerContext,ChannelPipeline這三者的關係很特別,相輔相成,一個ChannelPipeline中能夠有3多個ChannelHandler實例,而每個ChannelHandler實例與ChannelPipeline之間的橋樑就是ChannelHandlerContext實例,
ChannelHandlerContext用於得到上下文信息,如得到遠程地址。
一個channelPipeline中有多個channelHandler時,且這些channelHandler中有一樣的方法時,例如channelActive方法,只會調用處在第一個的channelHandler中的channelActive方法,若是想要調用後續的channelHandler的同名的方法就須要調用以「fire」爲開頭的方法,如ctx.fireExceptionCaught(cause);bootstrap

三、EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();瀏覽器

NioEventLoopGroup是用來處理I/O操做的多線程事件循環器,Netty提供了許多不一樣的EventLoopGroup的實現用來處理不一樣傳輸協議。咱們實現了一個服務端的應用,會有2個NioEventLoopGroup會被使用。第一個常常被叫作‘boss’,用來接收進來的鏈接。第二個常常被叫作‘worker’,用來處理已經被接收的鏈接,一旦‘boss’接收到鏈接,就會把鏈接信息註冊到‘worker’上。如何知道多少個線程已經被使用,如何映射到已經建立的channel上都須要依賴於EventLoopGroup的實現,而且能夠經過構造函數來配置他們的關係。

服務器端 bootstrap.childHandler   客戶端:bootstrap.handler
handler針對的是boss發揮做用,處理boss相關信息,如:鏈接來了後,處理相關日誌輸出;
childhandler針對worker,boss把鏈接交給worker後,由childhandler裏面對象對worker裏面nio線程發揮做用

2018-7-27

netty 多客戶端鏈接與通訊 
實現多客戶端鏈接,
需求1:A、B、C-》Server,一、A鏈接,二、B鏈接,S打印B鏈接,S告訴A,B上線,三、C上線,S打印C上線,廣播給AB,通知C上線
需求2:ABC都創建鏈接,A發消息,ABC都受到消息,A顯示本身發的消息,BC顯示消息來自A

經過handlerAdded,獲取添加的channel,使用channelgroup,向channel組裏的已有通道廣播

源碼 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/thirdexample

##netty讀寫檢測機制與長鏈接要素------心跳

一、手機端和服務器端創建長鏈接,客戶端沒退出應用,而後客戶端開了飛行模式,則服務器端與客戶端沒法感知鏈接已斷,相應方法如handlerRemoved方法不會調用。 經過心跳,app向服務器端發心跳包,服務器端收到後,再向app發送ack。若是客戶端長時間沒法收到反饋消息,則斷開

二、IdleStateHandler用來檢測空閒狀態,設置讀寫操做有效時間, userEventTriggered 出發某個事件被觸發後調用該方法,將事件轉發給管道pipeline的下一個handler對象。userEventTriggered 某個事件被觸發後調用該方法,將事件轉發給管道pipeline的下一個handler對象

源碼 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/fourthexample

2018-7-30

netty對websocket的支持

1、websocket解決http存在的問題, 一、http是無狀態的,客戶端發送兩次請求,單從協議自己沒法識別兩次關係、存了哪些信息,像cookie、session用來解決這些問題, 二、基於請求響應模式的協議,http1.0中請求與響應以前先創建鏈接,請求發起方是瀏覽器,響應完成後斷開鏈接,如此反覆。HTTP1.1,增長keep-alive,客戶端和服務端保持一個短期的持續鏈接,這個時間內,客戶端與服務端只會創建一個連接,以後的請求複用該鏈接

2、假長鏈接,運用輪詢的結束,客戶端定時發請求,http包含兩部分,header和body,header必帶,頭信息佔據的大小遠大於內容。

3、websocket實現瀏覽器與服務器之間的長鏈接,雙方是對等的實體,能夠互發信息。長鏈接在初次創建的時候,客戶端向服務端發送請求(包括頭信息),以後不用包括頭信息,真正發送數據自己

websocket自己是構建在http協議上的升級版協議,客戶端向向服務器端發請求創建鏈接(http鏈接),header裏攜帶了websocket相關的參數,根據這些參數,服務端經過upgrade這個操做把http鏈接升級成websocket

websocket是html5規範的一部分

2018-7-31

一、netty 對於處理請求是分塊或分段方式,客戶端向服務端發送請求,長度1000,netty可能會分紅10段,每段會走一個完整的流程,咱們本身處理器的channelread0,只讀到一段

二、HttpObjectAggregator(len)把分段的請求(響應)聚合成一個完整的請求(響應),len以字節的方式來聚合內容的最大長度,若是聚合的內容超過了長度,調用handleOversizedMessage

三、WebSocketServerProtocolHandler 會處理關於websocket繁重的工做,負責鏈接握手、以及處理心跳相關的內容,WebSocketServerProtocolHandler("/ws")其中/ws是指websocket uri的地址 如ws://localhost:8899/'ws' WebSocketServerProtocolHandler的ws是指請求地址裏的第二個ws

##netty實現服務端和客戶端的長鏈接通訊

源碼 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/fifthexample
需求,實現網頁經過websocket發送數據,服務端收到後反饋消息
在瀏覽器的ws:/localhost:8899/ws  header中,Status Code:101 Switching Protocols,轉換協議  http->ws
在請求頭裏Request Headers裏Upgrade:websocket,雖然訪問ws這個請求,可是須要http先去創建鏈接,創建完成後,再upgrade(升級)到websocket,因此說websocket是在http之上的協議

2018-8-1

##google protobuf使用方式

源碼 https://github.com/chris1132/netty_lecture/src/main/java/com/chovy/netty/sixthexample
1、protobuf 進行rpc數據傳輸,用來自定協議,能夠更好的、體積更小的對數據編碼解碼,即序列化反序列化(編碼、解碼)過程。rpc開發中經常使用的庫
2、RMI:remote method invocation,遠程方法調用。(只針對java,client和server都必須是java) 客戶端:stub,服務端:skeleton
經過網絡傳輸,A->(調用的對象、方法、參數)序列化成字節碼-》網絡傳輸-》B-》接收字節碼,反序列化轉換成,調用特定對象、方法。
RPC:remote procedure call 遠程過程調用  用socket傳輸
RPC比RMI的優點,跨語言調用,如客戶端用python,服務端用java,客戶端能夠調用本身的一個方法,觸發服務端的方法
RPC編寫模式,:
一、定義接口說明文件(idl):描述對象、對象成員、接口方法等一系列信息。
二、經過rpc框架所提供的編譯器,將接口說明文件編譯成具體文件
三、在客戶端與服務器端分別引入RPC編譯器所生成的文件,便可像調用本地方法同樣調用遠程方法
決定rpc框架效率看編解碼效率
在公司內網中更推薦用rpc方式進行,減小基於http通訊帶來的損耗。
2018-8-2
使用protocol-buffer構建對象,實現編解碼
需求,客戶端A,服務器B,A構造對象,發給服務器端,B收到後,打印對象信息,把另外一個對象發給A。

用proto文件建立java代碼指令,protoc -I=src/protobuf  --java_out=src/main/java src/protobuf/StuffInfo.proto

2018-8-3
接昨天,已完成昨天需求,待解決問題
pipeline.addLast(new ProtobufDecoder(StuffInfo.Teacher.getDefaultInstance()))   //StuffInfo.Teacher編碼對象寫死,不靈活,

2018-8-6
解決方案,在發送消息外再包一層,見StuffInfo.proto,經過枚舉列舉各消息類型,再經過一個字段標識本次消息傳遞的是哪一個消息類型
netty基於protocolbuffer這種數據傳遞過程,對於具體用哪一種方法或數據類型來處理請求,存在判斷繁雜問題,由於,一段向另外一段發送數據時候,接收方要能判斷對方發送哪一種數據類型,經過if-else去尋找匹配的數據類型
而springmvc和netty相比比,springmvc路徑路由很清晰直觀,如: @RequestMapping(value="../xx/",method=RequestMethod.GET),下面對於一個處理方法。由於springmvc 有dispatcherServlet(控制器),c向s發起的全部請求,
都通過dispatcherServlet,再分發給不一樣的controller,springmvc在啓動的時候,找到url和方法對應關係,把對應關係保存(如map),s收到請求後,經過url匹配具體方法。

使用Git做爲版本控制系統

不建議。。git submodule:  git 倉庫裏的一個倉庫,如netty_lecture是已有的工程,protobuf生成的java代碼爲protobuf-java工程,經過git submodule把protobuf-java引入到netty_lecture,當protobuf-java本地發生變化,提交遠程倉庫後,切到netty_lecture目錄下,經過git pull,把protobuf-java更新到netty_lecture。問題:分支切換紊亂,A中引入了中間工程B,若在A中對B進行修改,在把B更新到遠程倉庫,會發生錯誤

建議。。git subtree

##io、nio回顧 https://blog.csdn.net/u010530712/article/details/82021416

2018-8-27

###零拷貝深刻剖析及用戶空間與內核空間切換方式###

http://www.javashuo.com/article/p-exgadnoe-hd.html