Netty入門執行個體及分析

來源:互聯網
上載者:User

標籤:netty   clientbootstrap   serverbootstrap   channel   


什麼是netty?下面是官方文檔的簡介: The Netty project  is an effort to providean asynchronous event-driven network application framework and tools for rapid development of maintainable high performance and high scalability protocol servers and clients. In other words, Netty isa NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP/IP socket server.

下面寫一個簡單的執行個體:1.用戶端細節分析
ChannelFactory是建立一個通道(和一次具體的通訊實體關聯如網路通訊端)的主要介面,比如NioServerSocketChannelFactory 會建立一個Channel,有基於NIO的服務通訊端作為底層的通訊實體。一旦一個新的通道建立,那麼對應的ChannelPipeline就會開始處理相關的ChannelEvents。 
NioClientSocketChannelFactory會建立一個用戶端的基於NIO的SocketChannel,利用非阻塞IO模型來高效處理這些並發的串連。其中有兩種類型的線程, boss thread 和 worker thread,每個NioClientSocketChannelFactory 有一個boss thread,它主要是有請求要發出時試圖進行一次串連,串連成功後,將這個串連的通道交付給一個worker thread,接下來這個worker thread 為一個或多個通道執行非阻塞的讀寫服務。

ClientBootstrap只是一個輔助函數,不會分配或者管理任何資源,管理資源是由構造器中指定的ChannelFactory完成的。所以從同一個ChannelFactory衍生出多個ClientBootstrap是可以的,從而為不同的Channel應用不同的設定。connect()方法會根據指定的SocketAddress試圖建立串連,如果本地地址沒有設定,就會自動分配,等價於:ClientBootstrap b = ....;b.connect(remoteAddress, b.getOption("localAddress"));

靜態方法 Channels.pipeline(ChannelHandler... handlers)用參數所指定的ChannelHandler 來建立一個新的ChannelPipeline,當然它們是有順序的,我們也可以自己一個一個的添加。  public  static ChannelPipeline pipeline(ChannelHandler... handlers) {         if (handlers ==  null) {             throw  new NullPointerException( "handlers");        }
         ChannelPipeline newPipeline =  pipeline ();         for ( int i = 0; i < handlers. length; i ++) {            ChannelHandler h = handlers[i];             if (h ==  null) {                 break;            }            newPipeline.addLast(ConversionUtil.  toString(i), h);        }         return newPipeline;    }
2. 伺服器端細節分析
伺服器端構建的基本流程和用戶端類似,只是這裡的ChannelFactory,Bootstrap 都要滿足作為server的特性。NioServerSocketChannelFactory建立伺服器端的,基於NIO的ServerSocketChannel,仍然是非阻塞模式。每個綁定的ServerSocketChannel 有自身的boos thread,比如說開啟監聽了兩個連接埠 80,443,那麼就會有兩個boss thread,各自負責各自連接埠的串連請求,直到那個連接埠解除綁定定,然後將接受的串連請求交給worker thread去處理。
這裡是連線導向傳輸的ClientBootstrap 和  ServerBootstrap ,如果想用UDP的話就選 ConnectionlessBootstrap。
3. ChannelHandler的常見用法就會根據具體的事件類型做出具體的處理,牽扯到讀寫管道,而且有上下流的情況。
一個簡單的netty例子:TimeClientl.java
import java.net.InetSocketAddress;import java.util.concurrent.Executors;import org.jboss.netty.bootstrap.ClientBootstrap;import org.jboss.netty.channel.ChannelFactory;import org.jboss.netty.channel.ChannelPipeline;import org.jboss.netty.channel.ChannelPipelineFactory;import org.jboss.netty.channel.Channels;import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;public class TimeClient {public static void main(String[] args) {String host = args[0];int port = Integer.parseInt(args[1]);ChannelFactory factory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());ClientBootstrap bootstrap = new ClientBootstrap(factory);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {@Overridepublic ChannelPipeline getPipeline() throws Exception {return Channels.pipeline(new TimeClientHandler2());}});bootstrap.connect(new InetSocketAddress(host, port));  //}}


TimeClientHandler.java
import java.util.Date;import org.jboss.netty.buffer.ChannelBuffer;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.channel.ExceptionEvent;import org.jboss.netty.channel.MessageEvent;import org.jboss.netty.channel.SimpleChannelHandler;public class TimeClientHandler extends SimpleChannelHandler{@Overridepublic void messageReceived(ChannelHandlerContext ctx, MessageEvent e)throws Exception {ChannelBuffer buffer = (ChannelBuffer)e.getMessage();long currentTimeMills = buffer.readInt() * 1000L;System.out.println(new Date(currentTimeMills));e.getChannel().close();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)throws Exception {e.getCause().printStackTrace();Channel c = e.getChannel();c.close();}}



TimeServer.java
import java.net.InetSocketAddress;import java.util.concurrent.Executors;import org.jboss.netty.bootstrap.ServerBootstrap;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelFactory;import org.jboss.netty.channel.ChannelPipeline;import org.jboss.netty.channel.ChannelPipelineFactory;import org.jboss.netty.channel.Channels;import org.jboss.netty.channel.group.ChannelGroup;import org.jboss.netty.channel.group.ChannelGroupFuture;import org.jboss.netty.channel.group.DefaultChannelGroup;import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;public class TimeServer {public static ChannelGroup allChannels = new DefaultChannelGroup("time-server");public static void main(String[] args) {ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool());ServerBootstrap bootstrap = new ServerBootstrap(factory);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {@Overridepublic ChannelPipeline getPipeline() throws Exception {return Channels.pipeline(new TimeServerHandler2(), new TimeEncoder());}});bootstrap.setOption("reuseAddr", true);bootstrap.setOption("child.tcpNoDelay", true);bootstrap.setOption("child.keepAlive", true);Channel channel = bootstrap.bind(new InetSocketAddress(8080));allChannels.add(channel);//waitForShutdownCommand();  this is a imaginary logic:for instance //when there is accepted connection we close this server ;if(allChannels.size() >=2){ChannelGroupFuture f = allChannels.close();f.awaitUninterruptibly();factory.releaseExternalResources();}}}



TimeServerHandler.java
import org.jboss.netty.buffer.ChannelBuffer;import org.jboss.netty.buffer.ChannelBuffers;import org.jboss.netty.channel.Channel;import org.jboss.netty.channel.ChannelFuture;import org.jboss.netty.channel.ChannelFutureListener;import org.jboss.netty.channel.ChannelHandlerContext;import org.jboss.netty.channel.ChannelStateEvent;import org.jboss.netty.channel.ExceptionEvent;import org.jboss.netty.channel.SimpleChannelHandler;public class TimeServerHandler extends SimpleChannelHandler{@Overridepublic void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)throws Exception {Channel ch = e.getChannel();ChannelBuffer time = ChannelBuffers.buffer(4); //sizeof inttime.writeInt((int)(System.currentTimeMillis()/1000L + 2208988800L));ChannelFuture cf = ch.write(time);cf.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {Channel ch = future.getChannel();ch.close();}});}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)throws Exception {e.getCause().printStackTrace();Channel c = e.getChannel();c.close();}}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.