Netty概述

文章轉載自:http://lippeng.iteye.com/blog/1907279


Netty是什麼?

 

本質:JBoss做的一個Jar包

 

目的:快速開發高性能、高可靠性的網絡服務器和客戶端程序

 

優點:提供異步的、事件驅動的網絡應用程序框架和工具

 

通俗的說:一個好使的處理Socket的東東

 

 

如果沒有Netty?

 

遠古:java.net + java.io

 

近代:java.nio

 

其他:Mina,Grizzly

 

爲什麼不是Mina?

 

1、都是Trustin Lee的作品,Netty更晚;

2、Mina將內核和一些特性的聯繫過於緊密,使得用戶在不需要這些特性的時候無法脫離,相比下性能會有所下降,Netty解決了這個設計問題;

3、Netty的文檔更清晰,很多Mina的特性在Netty裏都有;

4、Netty更新週期更短,新版本的發佈比較快;

5、它們的架構差別不大,Mina靠apache生存,而Netty靠jboss,和jboss的結合度非常高,Netty有對google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);

6、Netty比Mina使用起來更簡單,Netty裏你可以自定義的處理upstream events 或/和 downstream events,可以使用decoder和encoder來解碼和編碼發送內容;

7、Netty和Mina在處理UDP時有一些不同,Netty將UDP無連接的特性暴露出來;而Mina對UDP進行了高級層次的抽象,可以把UDP當成"面向連接"的協議,而要Netty做到這一點比較困難。

 

 

Netty的特性

 

設計

統一的API,適用於不同的協議(阻塞和非阻塞)

基於靈活、可擴展的事件驅動模型

高度可定製的線程模型

可靠的無連接數據Socket支持(UDP)

 

性能

更好的吞吐量,低延遲

更省資源

儘量減少不必要的內存拷貝

 

安全

完整的SSL/TLS和STARTTLS的支持

能在Applet與Android的限制環境運行良好

 

健壯性

不再因過快、過慢或超負載連接導致OutOfMemoryError

不再有在高速網絡環境下NIO讀寫頻率不一致的問題

 

易用

完善的JavaDoc,用戶指南和樣例

簡潔簡單

僅信賴於JDK1.5

 

看例子吧!

 

Server端:

 

Java代碼  收藏代碼
  1. package me.hello.netty;  
  2.   
  3. import org.jboss.netty.bootstrap.ServerBootstrap;  
  4. import org.jboss.netty.channel.*;  
  5. import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;  
  6. import org.jboss.netty.handler.codec.string.StringDecoder;  
  7. import org.jboss.netty.handler.codec.string.StringEncoder;  
  8.   
  9. import java.net.InetSocketAddress;  
  10. import java.util.concurrent.Executors;  
  11.   
  12. /** 
  13.  * God Bless You! 
  14.  * Author: Fangniude 
  15.  * Date: 2013-07-15 
  16.  */  
  17. public class NettyServer {  
  18.     public static void main(String[] args) {  
  19.         ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  
  20.   
  21.         // Set up the default event pipeline.  
  22.         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  23.             @Override  
  24.             public ChannelPipeline getPipeline() throws Exception {  
  25.                 return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ServerHandler());  
  26.             }  
  27.         });  
  28.   
  29.         // Bind and start to accept incoming connections.  
  30.         Channel bind = bootstrap.bind(new InetSocketAddress(8000));  
  31.         System.out.println("Server已經啓動,監聽端口: " + bind.getLocalAddress() + ", 等待客戶端註冊。。。");  
  32.     }  
  33.   
  34.     private static class ServerHandler extends SimpleChannelHandler {  
  35.         @Override  
  36.         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {  
  37.             if (e.getMessage() instanceof String) {  
  38.                 String message = (String) e.getMessage();  
  39.                 System.out.println("Client發來:" + message);  
  40.   
  41.                 e.getChannel().write("Server已收到剛發送的:" + message);  
  42.   
  43.                 System.out.println("\n等待客戶端輸入。。。");  
  44.             }  
  45.   
  46.             super.messageReceived(ctx, e);  
  47.         }  
  48.   
  49.         @Override  
  50.         public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
  51.             super.exceptionCaught(ctx, e);  
  52.         }  
  53.   
  54.         @Override  
  55.         public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {  
  56.             System.out.println("有一個客戶端註冊上來了。。。");  
  57.             System.out.println("Client:" + e.getChannel().getRemoteAddress());  
  58.             System.out.println("Server:" + e.getChannel().getLocalAddress());  
  59.             System.out.println("\n等待客戶端輸入。。。");  
  60.             super.channelConnected(ctx, e);  
  61.         }  
  62.     }  
  63. }  

 

客戶端:

 

Java代碼  收藏代碼
  1. package me.hello.netty;  
  2.   
  3. import org.jboss.netty.bootstrap.ClientBootstrap;  
  4. import org.jboss.netty.channel.*;  
  5. import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;  
  6. import org.jboss.netty.handler.codec.string.StringDecoder;  
  7. import org.jboss.netty.handler.codec.string.StringEncoder;  
  8.   
  9. import java.io.BufferedReader;  
  10. import java.io.InputStreamReader;  
  11. import java.net.InetSocketAddress;  
  12. import java.util.concurrent.Executors;  
  13.   
  14. /** 
  15.  * God Bless You! 
  16.  * Author: Fangniude 
  17.  * Date: 2013-07-15 
  18.  */  
  19. public class NettyClient {  
  20.   
  21.     public static void main(String[] args) {  
  22.         // Configure the client.  
  23.         ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));  
  24.   
  25.         // Set up the default event pipeline.  
  26.         bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
  27.             @Override  
  28.             public ChannelPipeline getPipeline() throws Exception {  
  29.                 return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ClientHandler());  
  30.             }  
  31.         });  
  32.   
  33.         // Start the connection attempt.  
  34.         ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost"8000));  
  35.   
  36.         // Wait until the connection is closed or the connection attempt fails.  
  37.         future.getChannel().getCloseFuture().awaitUninterruptibly();  
  38.   
  39.         // Shut down thread pools to exit.  
  40.         bootstrap.releaseExternalResources();  
  41.     }  
  42.   
  43.     private static class ClientHandler extends SimpleChannelHandler {  
  44.         private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));  
  45.   
  46.         @Override  
  47.         public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {  
  48.             if (e.getMessage() instanceof String) {  
  49.                 String message = (String) e.getMessage();  
  50.                 System.out.println(message);  
  51.   
  52.                 e.getChannel().write(sin.readLine());  
  53.   
  54.                 System.out.println("\n等待客戶端輸入。。。");  
  55.             }  
  56.   
  57.             super.messageReceived(ctx, e);  
  58.         }  
  59.   
  60.         @Override  
  61.         public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {  
  62.             System.out.println("已經與Server建立連接。。。。");  
  63.             System.out.println("\n請輸入要發送的信息:");  
  64.             super.channelConnected(ctx, e);  
  65.   
  66.             e.getChannel().write(sin.readLine());  
  67.         }  
  68.     }  
  69. }  

 

Netty整體架構



 

Netty組件

 

ChannelFactory

Boss

Worker

Channel

ChannelEvent

Pipeline

ChannelContext

Handler

Sink

 

Server端核心類

NioServerSocketChannelFactory

NioServerBossPool 

NioWorkerPool

NioServerBoss

NioWorker

NioServerSocketChannel

NioAcceptedSocketChannel

DefaultChannelPipeline

NioServerSocketPipelineSink

Channels

 

 

ChannelFactory

Channel工廠,很重要的類

保存啓動的相關參數

 

NioServerSocketChannelFactory

NioClientSocketChannelFactory

NioDatagramChannelFactory

 

這是Nio的,還有Oio和Local的

 

 

SelectorPool

 

Selector的線程池

 

NioServerBossPool 默認線程數:1

NioClientBossPool      1

NioWorkerPool      2 * Processor

NioDatagramWorkerPool

 

 

Selector

 

選擇器,很核心的組件

 

NioServerBoss

NioClientBoss

NioWorker

NioDatagramWorker

 

 

Channel

 

通道

 

NioServerSocketChannel

NioClientSocketChannel

NioAcceptedSocketChannel

NioDatagramChannel

 

Sink

負責和底層的交互

如bind,Write,Close等

 

NioServerSocketPipelineSink

NioClientSocketPipelineSink

NioDatagramPipelineSink

 

Pipeline

負責維護所有的Handler

 

ChannelContext

一個Channel一個,是Handler和Pipeline的中間件

 

Handler

對Channel事件的處理器

 

 

ChannelPipeline

 



 

 

 

優秀的設計----事件驅動



 

 

優秀的設計----線程模型



 

注意事項

 

解碼時的Position

 

Channel的關閉

 

更多Handler

 

 

Channel的關閉

 

用完的Channel,可以直接關閉;

1、ChannelFuture加Listener

2、writeComplete

 

一段時間沒用,也可以關閉

TimeoutHandler


發佈了26 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章