摘要:是一個高性能事件驅(qū)動的異步的非堵塞的框架,用于建立等底層的連接,基于可以建立高性能的服務(wù)器。在中提供了兩套,一套是針對標(biāo)準(zhǔn)輸入輸出,另一套就是網(wǎng)絡(luò)編程。和是標(biāo)準(zhǔn)中的核心對象是對原中流的模擬,任何來源和目的數(shù)據(jù)都必須通過一個對象。
Netty是一個高性能 事件驅(qū)動的異步的非堵塞的IO(NIO)框架,用于建立TCP等底層的連接,基于Netty可以建立高性能的Http服務(wù)器。
1、首先來復(fù)習(xí)下非堵塞IO(NIO)
NIO這個庫是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但實現(xiàn)方式不同,NIO主要用到的是塊,所以NIO的效率要比IO高很多。
在Java API中提供了兩套NIO,一套是針對標(biāo)準(zhǔn)輸入輸出NIO,另一套就是網(wǎng)絡(luò)編程NIO。
*Buffer和Channel是標(biāo)準(zhǔn)NIO中的核心對象*
Channel是對原IO中流的模擬,任何來源和目的數(shù)據(jù)都必須通過一個Channel對象。一個Buffer實質(zhì)上是一個容器對象,發(fā)給Channel的所有對象都必須先放到Buffer中;同樣的,從Channel中讀取的任何數(shù)據(jù)都要讀到Buffer中。
網(wǎng)絡(luò)編程NIO中還有一個核心對象Selector,它可以注冊到很多個Channel上,監(jiān)聽各個Channel上發(fā)生的事件,并且能夠根據(jù)事件情況決定Channel讀寫。這樣,通過一個線程管理多個Channel,就可以處理大量網(wǎng)絡(luò)連接了。
Selector 就是注冊對各種 I/O 事件興趣的地方,而且當(dāng)那些事件發(fā)生時,就是這個對象告訴你所發(fā)生的事件。
Selector selector = Selector.open(); //創(chuàng)建一個selector
為了能讓Channel和Selector配合使用,我們需要把Channel注冊到Selector上。通過調(diào)用channel.register()方法來實現(xiàn)注冊:
channel.configureBlocking(false); //設(shè)置成異步IO
SelectionKey key =channel.register(selector,SelectionKey.OP_READ); //對所關(guān)心的事件進(jìn)行注冊(connet,accept,read,write)
SelectionKey 代表這個通道在此 Selector 上的這個注冊。
2、異步
CallBack:回調(diào)是異步處理經(jīng)常用到的編程模式,回調(diào)函數(shù)通常被綁定到一個方法上,并且在方法完成之后才執(zhí)行,這種處理方式在javascript當(dāng)中得到了充分的運用。回調(diào)給我們帶來的難題是當(dāng)一個問題處理過程中涉及很多回調(diào)時,代碼是很難讀的。
Futures:Futures是一種抽象,它代表一個事情的執(zhí)行過程中的一些關(guān)鍵點,我們通過Future就可以知道任務(wù)的執(zhí)行情況,比如當(dāng)任務(wù)沒完成時我們可以做一些其它事情。它給我們帶來的難題是我們需要去判斷future的值來確定任務(wù)的執(zhí)行狀態(tài)。
3、netty到底怎么工作的呢?
直接來看個最簡單的實例
服務(wù)器端
public class EchoServer { private final static int port = 8007; public void start() throws InterruptedException{ ServerBootstrap bootstrap = new ServerBootstrap(); //引導(dǎo)輔助程序 EventLoopGroup group = new NioEventLoopGroup(); //通過nio的方式接受連接和處理連接 try { bootstrap.group(group) .channel(NioServerSocketChannel.class) //設(shè)置nio類型的channel .localAddress(new InetSocketAddress(port)) //設(shè)置監(jiān)聽端口 .childHandler(new ChannelInitializer() { //有連接到達(dá)時會創(chuàng)建一個channel // pipline 管理channel中的handler,在channel隊列中添加一個handler來處理業(yè)務(wù) @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("myHandler", new EchoServerHandler()); //ch.pipeline().addLast("idleStateHandler",new? IdleStateHandler(0, 0, 180)); } }); ChannelFuture future = bootstrap.bind().sync(); //配置完成,綁定server,并通過sync同步方法阻塞直到綁定成功 System.out.println(EchoServer.class.getName() + " started and listen on " + future.channel().localAddress()); future.channel().closeFuture().sync(); //應(yīng)用程序會一直等待,直到channel關(guān)閉 } catch (Exception e) { e.getMessage(); }finally { group.shutdownGracefully().sync(); } }
創(chuàng)建一個ServerBootstrap實例
創(chuàng)建一個EventLoopGroup來處理各種事件,如處理鏈接請求,發(fā)送接收數(shù)據(jù)等。
定義本地InetSocketAddress( port)好讓Server綁定
創(chuàng)建childHandler來處理每一個鏈接請求
所有準(zhǔn)備好之后調(diào)用ServerBootstrap.bind()方法綁定Server
handler 處理核心業(yè)務(wù)
@Sharable //注解@Sharable可以讓它在channels間共享?? public class EchoServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception { ByteBuf buf = ctx.alloc().buffer(); buf.writeBytes("Hello World".getBytes()); ctx.write(buf); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
客戶端 連接
public class EchoClient { private final int port; private final String hostIp; public EchoClient(int port, String hostIp) { this.port = port; this.hostIp = hostIp; } public void start() throws InterruptedException { Bootstrap bootstrap = new Bootstrap(); EventLoopGroup group = new NioEventLoopGroup(); try { bootstrap.group(group).channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress(hostIp, port)) .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture future = bootstrap.connect().sync(); future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { System.out.println("client connected"); } else { System.out.println("server attemp failed"); future.cause().printStackTrace(); } } }); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { group.shutdownGracefully().sync(); } }
客戶端handler
@Sharable public class EchoClientHandler extends SimpleChannelInboundHandler{ /**? ?? ? *此方法會在連接到服務(wù)器后被調(diào)用 ? ?? ? * */ ? ? ? public void channelActive(ChannelHandlerContext ctx) {? ? ? System.out.println("Netty rocks!"); ? ? ? ? ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); ? ? ? } ? /** * 接收到服務(wù)器數(shù)據(jù)時調(diào)用 */ @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { System.out.println("Client received: " + ByteBufUtil.hexDump(msg.readBytes(msg.readableBytes()))); ? } /**? ?? ? *捕捉到異常 ? ?? ? * */ ? ? ? public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ? ? ? ? ? cause.printStackTrace(); ? ? ? ? ? ctx.close(); ? ? ? } ? }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66352.html
摘要:支持很多協(xié)議,并且提供用于數(shù)據(jù)處理的容器。我們已經(jīng)知道由特定事件觸發(fā)。可專用于幾乎所有的動作,包括將一個對象轉(zhuǎn)為字節(jié)或相反,執(zhí)行過程中拋出的異常處理。提供了一個容器給鏈并提供了一個用于管理沿著鏈入站和出站事件的流動。子類通過進(jìn)行注冊。 前兩天寫了一點netty相關(guān)的知識,并寫了一個demo,但是對其原理還是沒有深入,今天我們來做一次研究吧 首先讓我們來認(rèn)識一下netty的幾個核心人物吧...
摘要:它使用了事件通知以確定在一組非阻塞套接字中有哪些已經(jīng)就緒能夠進(jìn)行相關(guān)的操作。目前,可以把看作是傳入入站或者傳出出站數(shù)據(jù)的載體。出站事件是未來將會觸發(fā)的某個動作的操作結(jié)果,這些動作包括打開或者關(guān)閉到遠(yuǎn)程節(jié)點的連接將數(shù)據(jù)寫到或者沖刷到套接字。 netty的概念 定義 Netty 是一款異步的事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架,支持快速地開發(fā)可維護(hù)的高性能的面向協(xié)議的服務(wù)器和客戶端。我們可以很簡單的...
摘要:最后五年工作經(jīng)驗以上。所以我希望大家也可以深入某項核心技術(shù)去好好研究。公眾號貓說現(xiàn)架構(gòu)設(shè)計碼農(nóng)兼創(chuàng)業(yè)技術(shù)顧問,不羈平庸,熱愛開源,雜談程序人生與不定期干貨。 本博客 貓叔的博客,轉(zhuǎn)載請申明出處 前言 感謝粉絲提問,由于我最近工作較忙,所以今晚抽空回復(fù)問題,可能有點倉促,回答的不是很全,不過希望能對你有所幫助。 整理自己的技術(shù)棧 首先,我需要你整理出自己一份滿意的簡歷,我希望程序員可以每...
摘要:,一般稱為選擇器。它是核心組件中的一個,用于輪詢一個或多個的狀態(tài)是否處于可讀可寫。如此,一個線程就可以管理多個,也就說可以管理多個網(wǎng)絡(luò)連接。 Selector , 一般稱為選擇器。它是 Java NIO 核心組件中的一個,用于輪詢一個或多個 NIO Channel 的狀態(tài)是否處于可讀、可寫。如此,一個線程就可以管理多個 Channel ,也就說可以管理多個網(wǎng)絡(luò)連接。也因此,Select...
摘要:前提好幾周沒更新博客了,對不斷支持我博客的童鞋們說聲抱歉了。熟悉我的人都知道我寫博客的時間比較早,而且堅持的時間也比較久,一直到現(xiàn)在也是一直保持著更新狀態(tài)。 showImg(https://segmentfault.com/img/remote/1460000014076586?w=1920&h=1080); 前提 好幾周沒更新博客了,對不斷支持我博客的童鞋們說聲:抱歉了!。自己這段時...
閱讀 1375·2019-08-30 15:55
閱讀 1655·2019-08-26 10:21
閱讀 3447·2019-08-23 18:28
閱讀 3383·2019-08-23 15:38
閱讀 753·2019-08-23 15:24
閱讀 2143·2019-08-23 13:59
閱讀 785·2019-08-23 11:31
閱讀 2875·2019-08-23 10:53