Netty是一个NIO client-server框架。Netty提供了高层次的抽象来简化TCP和UDP服务器的编程。

  Netty框架由三部分组成:Transport Services, Protocol Support以及Core。

    Transport Services由Socket Datagram,HTTP Tunnel以及In-VM Pipe组成。

    Protocol Support由Http & WebSocket, SSL-StartTLS,Google Protobuf,zlib/gzip Compression,Large File Transfer,RTSP以及Legacy Text-Binary Protocols with Unit Testability组成。

    Core由Extensible Event Model,Universal Communication API和Zero-Copy-Capable Rich Byte Buffer组成。

  整个Netty的API都是异步的。

    Callbacks(回调)

      一个回调是被传递到并且执行完该方法。回调有个问题是当使用链式调用很多不同的方法会导致线性代码。

public class Worker{
  public void doWork(){
    Fecher fetcher = new MyFetcher(new Data(1, 0));
    fetcher.fetchData(new FetcherCallback(){
      public void onError(Throwable cause){
        System.out.println("An error accour: " + cause.getMessage());
      }
     
      public void onData(Data data){
        System.out.println("Data received : " + data);
      }
    });
  }  
}

public interface Fetcher{
  void fetchData(FetcherCallback callback);
}

public class MyFetch implements Fetch{
  final Data data;
  public MyFetch(Data data){
    this.data = data;
  }
  public void fetchData(FetcherCallback callback){
    try{
      callback.onData(data);
    }catch(Exception e){
      callback.onError(e);
    }
  }
}

public interface FetcherCallback{
  void onData(Data data)  throw Exception;
  void onError(Throwable cause);    
}

public class Data{
  private int n;
  private int m;

  public Data(int n, int m){
    this.n = n;
    this.m = m;
  }
}

    Futures

      Futures是一个抽象的概念,它表示一个值,该值可能在某一点变得可用。一个Future可以获得计算完的结果,要么获得计算失败后的异常。Java在java.util.concurrent包中附带了Future接口,它使用Executor异步执行。

public class FutureExample{
  public static void main(String args[]) throws Exception{
    ExecutorService executor = Executors.newCachedThreadPool();
    Runnable task = new Runnable(){
      public void run(){
        System.out.println("task 1");
      }
    };
    Callable<Integer>  task2 = new Callable<Integer>(){
      public Integer call() throws Exception{
        return new Integer(100);
      }
    };
    Future<?> f1 = executor.sumbit(task1);
    Future<?> f2 = executor.sumbit(task2);
    System.out.println("task1 is completed? " + f1.isDone());
    System.out.println("task2 is completed? " + f2.isDone());
    while(fi.isDone){
      System.out.println("task1 completed");
      break;
    }
    while(f2.isDone()){
      System.out.println("return value by task2 :" + f2.get());
      break;
    }
  }
}

 

  NIO是一个比较底层的APIs,他依赖于操作系统的IO APIS。Java实现了统一的接口来操作IO,其在所有操作系统中的工作行为是一样的。
  ByteBuffer是一个数据容器。ByteBuffer允许包装一个byte[]来获得一个实例。Netty通过一些APIs对ByteBuffer进行构造,使用和操作,以此来解决NIO中的一些限制。

  很多Channel的实现支持Gather和Scatter。这个功能允许从多个ByteBuffer中读入或写入到多个ByteBuffer中,以提升性能。操作系统底层知道如何处理这些被写入/读出。若要分割的数据在多个不同的ByteBuffer中,使用Gather/Scatter是比较好的方式。Gather/Scatter功能会导致内存泄漏,需在JDK1.7版本以上使用。

  

  一个简单的demo

    Netty服务器

      一个Netty服务器主要有两部分组成:配置服务器功能(如线程,端口)以及实现服务器处理程序,它包含业务逻辑,决定当有一个请求连接或接收数据时该做什么。

      启动服务器应先创建一个ServerBootstrap对象,指定NioEventLoopGroup来接受和处理新连接,指定通道类型为NioServerSocketChannel,设置InetSocketAddress让服务器监听某个端口已等待客户端连接。调用childHandler指定连接后调用的ChannelHandler,该方法接受一个ChannelInitializer类型的参数,实现其initChannel方法,该方法用来设置ChannelHandler。直到绑定完成调用sync()方法会阻塞直到服务器完成绑定,然后等待通道关闭。

    Netty客户端

      一个Netty的客户端由连接服务器,写数据到服务器,等待接受服务器返回相同的数据和关闭连接四个步骤组成。

      创建一个客户端包含:创建Bootstrap对象用来引导启动客户端;创建EventLoopGroup对象并设置到Bootstrap中,EventLoopGroup可以理解为一个线程池,这个线程池用来处理连接,接收数据,发送数据;创建InetSocketAddress并设置到Boostrap中,InetSocketAddress是指定连接的服务器地址;添加一个ChannelHandler,客户端成功连接服务器后就会被执行;调用Bootstrap.connect()来连接服务器;最后关闭EventLoopGroup来释放资源。

      使用SimpleChannelInboundHandler的ChannelHandler来处理业务,通过重写父类的三个方法来处理感兴趣的事件:channelActive():客户端连接服务器后被调用;channelRead():从服务器接收到数据后调用;exceptionCaught():发生异常时被调用