標籤:java netty
學習 java netty (三) – Channel
前言:netty封裝的channel,看一下官網的定義
A nexus to a network socket or a component which is capable of I/O operations such as read, write, connect, and bind.
可以I/O操作(如讀,寫,串連和綁定)的連網通訊端或組件
A channel provides a user:
All I/O operations are asynchronous
netty中channel所有的操作都是非同步,請求將立即返回,但不保證請求完成
Channels are hierarchical
channel是分層的,一個Channel可以有一個父母,取決於它是如何建立的,比如一個SocketChannel(用戶端通訊端)被ServerSocketChannel(服務端通訊端)串連了,那麼ServerSocketChannel就類似與SocketChannel的 parent
Downcast to access transport-specific operations
向下轉型來訪問特定的傳輸協議,也就是說轉為子類型也可以訪問父類型的操作
Release resources
釋放資源,Channel內部也是Socket檔案控制代碼,我們要close()
Channel是netty抽象出來的介面,不同與Nio中的channel,netty中的Channel封裝了網路IO和網路IO相關的操作。功能非常多
源碼:
//Channel是一個介面類,繼承自AttributeMap和Comparable,AttributeMap是儲存屬性的一個map,Comparable介面強行對實現它的每個類的對象進行整體排序public interface Channel extends AttributeMap, Comparable<Channel> { //返回唯一標識 ChannelId id(); //返回被註冊的事件迴圈 EventLoop eventLoop(); //返回parent channel Channel parent(); //返回channel(socket)的配置 ChannelConfig config(); //判斷是否開啟,註冊,活躍 boolean isOpen(); boolean isRegistered(); //來源資料,可以獲得底層的tcp參數設定等 ChannelMetadata metadata(); //本地地址和遠端地址 SocketAddress localAddress(); SocketAddress remoteAddress(); //關閉Channel,返回ChannelFuture意味著是非同步,不阻塞立即返回,在未來Future我們可以獲得執行操作的狀態 ChannelFuture closeFuture(); //資料是可讀的 boolean isWritable(); long bytesBeforeWritable(); Unsafe unsafe(); ChannelPipeline pipeline(); ByteBufAllocator alloc(); ChannelPromise newPromise(); ChannelProgressivePromise newProgressivePromise(); ChannelFuture newSucceededFuture(); ChannelFuture newFailedFuture(Throwable cause); ChannelPromise voidPromise(); ChannelFuture bind(SocketAddress localAddress); ChannelFuture connect(SocketAddress remoteAddress); ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress); ChannelFuture disconnect(); ChannelFuture close(); ChannelFuture deregister(); ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise); ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise); ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise); ChannelFuture disconnect(ChannelPromise promise); ChannelFuture close(ChannelPromise promise); ChannelFuture deregister(ChannelPromise promise); Channel read(); ChannelFuture write(Object msg); ChannelFuture write(Object msg, ChannelPromise promise); Channel flush(); ChannelFuture writeAndFlush(Object msg, ChannelPromise promise); ChannelFuture writeAndFlush(Object msg); interface Unsafe
從介面類可以看出Channel操作是非常多的,後面的方法我沒有寫注釋,可以看見都是一些操作,返回ChannelFuture或者ChannelPromise,下面選一些重點來解釋。
Channel
封裝了許多協議tcp,udp等,通訊模型Nio,oio,Aio等,從上面可以看出對這些操作提供了一個整體的封裝介面就是Channel,必要的時候可以進行轉型。
介面中提供:
Channel的狀態,isOpen(),isWritable()
Channel的配置參數,config()
Channel支援的操作,bind(),read(),connect()
ChannelFuture
所有的Channel操作都是非同步,Channel的返回ChannelFuture的一些操作並不阻塞,而是立即返回,在未來某個時刻我們能夠獲得狀態來判斷該操作的狀態是完成還是進行還是取消。
注意ChannelFuture對象是操作一執行就立即返回了。ChannelFuture中提供的方法就是讓檢查操作完成狀況。
ChannelPromise
繼承關係:
Future <— ChannelFuture <— ChannelPromise
ChannelPromise繼承了ChannelFuture,ChannelFuture方法主要是判斷操作未來的狀態,而ChannelPromise除了繼承ChannelFuture的方法外,還實現了設定未來狀態的寫方法,
源碼上寫的是
Special {@link ChannelFuture} which is writable.
特殊的可寫的ChannelFuture
比如ChannelFuture返回錯誤等情況,當我們使用ChannelPromise時,就能改變返回結果,喚醒其他動作,有點線程中條件變數的感覺。
ChannelPipeline
說到ChannelPipeline先要說責任鏈設計模式,簡單來講就是將一些能處理請求的對象串起來形成一條鏈,被處理的對象不知道被誰處理,所以在這條處理鏈上輪尋過,該被誰處理誰就接受此對象進行處理。
現實生活的例子,比如上級指派了一個任務做一款軟體(被處理對象),放眼望去有一排攻城獅(處理請求對象),於是此任務在他們之間傳遞,每個攻城獅判斷自己是否能做,能做就接受請求。
pipeline就是這條責任鏈,我們可以往上面註冊,增添,刪除處理事件對象,然後當待處理對象在此pipeline上傳遞時,哪個處理事件對象能處理則接收它。
責任鏈設計模式
部分代碼:
public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new StringDecoder()); //分隔字元解碼器 DelimiterBasedFrameDecoder ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));}
上面添加了3個處理事件對象,字串解碼,分隔字元解碼,日誌資訊。當產生對應事件時,它們會接受並處理
注意:每個Channel在執行個體化的時候都會自動建立一個ChannelPipeline執行個體。ChannelPipeline是安全執行緒的,可以在任意時刻增加刪除。
ChannelHandler
ChannelHandler就是ChannelPipeline上面註冊的處理事件對象,每個ChannelHandler介面的實作類別完成一定的功能,並可以靈活的在Pipeline流水線上增加,ChannelHandler也稱為事件攔截器,遇到能處理的對象事件就攔截下來處理
ChannelHandler支援註解
@Sharable是多個Pipeline共用一個ChannelHandler
@skip是跳過此ChannelHandler
ChannelHandlerAdapter
ChannelHandlerAdapter給使用者提供了ChannelHandler的適配器,我們可以自訂類來繼承ChannelHandlerAdapter然後根據自己需要如何處理事件對象來重新實現ChannelHandler的方法。
例子:
public class ServerHandler extends ChannelHandlerAdapter { ServerHandler(){ System.out.println("ServerHandler被建立"); } //重寫此方法 public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception{ ctx.write(msg); System.out.println("發送msg"); ByteBuf buf = (ByteBuf)msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, "UTF-8"); System.out.println("server收到:" + body); ctx.write(resp); } public void channelReadComplete(ChannelHandlerContext ctx) throws Exception{ //將write資料先寫到緩衝區中,等到complete狀態再重新整理緩衝區 ctx.flush(); } public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){ //有錯誤時列印錯誤並且關閉ctx logger.log(Level.WARNING, "unexcepted exception from downstream", cause); ctx.close(); }}
到此Channel和Channel關係密切的類和介面差不多就簡單介紹完了,我們大致能知道它們的原理和它們的用法後,在看和使用其他繼承它們的拓展類就方便多了。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
學習 java netty (三) -- Channel