`

Netty初步之hello world .

 
阅读更多

Java的网络操作一直比较复杂,虽然说在加入NIO之后简单了些,但还不是我这些菜鸟玩得起的,由于存在大量低层操作和协议处理,所以在使用上面还是很难。迄今为止,还没有用NIO写出稳定可靠的网络操作,也许这和具体的应用需求较少也有关系吧。

大概也有人和我对NIO有同样的想法,他们最NIO进行了一些封装,所以就有了MIna和现在的Netty。

Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序[官方定义],整体来看其包含了以下内容:

1.提供了丰富的协议编解码支持,

2.实现自有的buffer系统,减少复制所带来的消耗,

3.整套channel的实现,

4.基于事件的过程流转以及完整的网络事件响应与扩展,

5.丰富的example。

有了Netty之后,网络编程最起码会大大简化,并且我们也不需要为性能问题担心,Netty并发两三万还是没什么太大问题的。已经有人进行过实验了。

本文主要是列举Netty初步使用的一个最基本的例子,具体的说明在代码中都有了,所以也不再重复。

java的学习是从Hello word开始的,Netty也从这里开始吧。
这里的例子比较简单,后面会慢慢的对Netty的一些复杂应用、Netty的原理进行一些解析。
1、ClientThread.java

  1. package HelloWord;  
  2.   
  3. import static org.jboss.netty.channel.Channels.pipeline;  
  4.   
  5. import java.net.InetSocketAddress;  
  6. import java.util.concurrent.Executors;  
  7.   
  8. import org.jboss.netty.bootstrap.ClientBootstrap;  
  9. import org.jboss.netty.channel.ChannelFuture;  
  10. import org.jboss.netty.channel.ChannelPipeline;  
  11. import org.jboss.netty.channel.ChannelPipelineFactory;  
  12. import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;  
  13. import org.jboss.netty.handler.codec.string.StringDecoder;  
  14. import org.jboss.netty.handler.codec.string.StringEncoder;  
  15.   
  16. /** 
  17.  * 启动一个client线程,用来间歇性的发送消息 
  18.  * @author Ransom 
  19.  */  
  20. public class ClientThread implements Runnable  
  21. {  
  22.    private ChannelFuture future;  
  23.     public ChannelFuture getFuture()  
  24. {  
  25.     return future;  
  26. }  
  27.   
  28. public void setFuture(ChannelFuture future)  
  29. {  
  30.     this.future = future;  
  31. }  
  32.   
  33.     @Override  
  34.     public void run()  
  35.     {  
  36.         /* 
  37.          * 实例化一个客户端Bootstrap实例, 
  38.          * NioClientSocketChannelFactory是Netty默认提供的。 
  39.          * 两个参数,一个是boss的线程池,一个是worker执行的线程池。 
  40.          * 两个线程池都使用了java.util.concurrent.Executors中的线程池来创建。 
  41.          */  
  42.         ClientBootstrap bootstrap = new ClientBootstrap(  
  43.                 new NioClientSocketChannelFactory(  
  44.                         Executors.newCachedThreadPool(),  
  45.                         Executors.newCachedThreadPool()));  
  46.           
  47.         /* 
  48.          * 设置piplineFactory, 
  49.          * 顾名思义,就是产生默认的pipline。 
  50.          *  pipline的实例是DefaultChannelPipeline 
  51.          *  提供了链式的事件通讯机制 
  52.          */  
  53.         bootstrap.setPipelineFactory(new ChannelPipelineFactory(){  
  54.             /* 
  55.              * (non-Javadoc) 
  56.              * @see org.jboss.netty.channel.ChannelPipelineFactory#getPipeline() 
  57.              */  
  58.             @Override  
  59.             public ChannelPipeline getPipeline() throws Exception  
  60.             {  
  61.                 /* 
  62.                  * 在DefaultChannelPipeline的过滤器 链中实现了 
  63.                  * encode 、decode、handler 
  64.                  * 其中encode实现自ChannelDownstreamHandler接口 
  65.                  * decode、Handler实现自ChannelUpstreamHandler接口 
  66.                  * 也就说明了在client发送消息的时候,默认按照顺序会先调用decode 
  67.                  * 在client接收到响应的时候,会按照顺序调用encode和Handler。 
  68.                  * 后面会有文章专门将ChannelDownstreamHandler和ChannelUpstreamHandler的调用顺序。 
  69.                  */  
  70.                 ChannelPipeline pipleline = pipeline();  
  71.                 pipleline.addLast("encode"new StringEncoder());  
  72.                 pipleline.addLast("decode"new StringDecoder());  
  73.                 pipleline.addLast("handler"new Handler());  
  74.                 return pipleline;  
  75.             }  
  76.         });  
  77.           
  78.         /* 
  79.          * 与127.0.0.1建立长连接。  
  80.          */  
  81.        future = bootstrap.connect(new InetSocketAddress("127.0.0.1"8080));  
  82.     }  
  83.       
  84.     /** 
  85.      * 发送消息至server 
  86.      */  
  87.     public void sendMsg()  
  88.     {  
  89.         if(future==nullreturn;  
  90.         String s = "Hello Word!";  
  91.         future.getChannel().write(s);  
  92.     }  
  93.       
  94. }  
package HelloWord;

import static org.jboss.netty.channel.Channels.pipeline;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * 启动一个client线程,用来间歇性的发送消息
 * @author Ransom
 */
public class ClientThread implements Runnable
{
   private ChannelFuture future;
    public ChannelFuture getFuture()
{
    return future;
}

public void setFuture(ChannelFuture future)
{
    this.future = future;
}

    @Override
    public void run()
    {
        /*
         * 实例化一个客户端Bootstrap实例,
         * NioClientSocketChannelFactory是Netty默认提供的。
         * 两个参数,一个是boss的线程池,一个是worker执行的线程池。
         * 两个线程池都使用了java.util.concurrent.Executors中的线程池来创建。
         */
        ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));
        
        /*
         * 设置piplineFactory,
         * 顾名思义,就是产生默认的pipline。
         *  pipline的实例是DefaultChannelPipeline
         *  提供了链式的事件通讯机制
         */
        bootstrap.setPipelineFactory(new ChannelPipelineFactory(){
            /*
             * (non-Javadoc)
             * @see org.jboss.netty.channel.ChannelPipelineFactory#getPipeline()
             */
            @Override
            public ChannelPipeline getPipeline() throws Exception
            {
                /*
                 * 在DefaultChannelPipeline的过滤器 链中实现了
                 * encode 、decode、handler
                 * 其中encode实现自ChannelDownstreamHandler接口
                 * decode、Handler实现自ChannelUpstreamHandler接口
                 * 也就说明了在client发送消息的时候,默认按照顺序会先调用decode
                 * 在client接收到响应的时候,会按照顺序调用encode和Handler。
                 * 后面会有文章专门将ChannelDownstreamHandler和ChannelUpstreamHandler的调用顺序。
                 */
                ChannelPipeline pipleline = pipeline();
                pipleline.addLast("encode", new StringEncoder());
                pipleline.addLast("decode", new StringDecoder());
                pipleline.addLast("handler", new Handler());
                return pipleline;
            }
        });
        
        /*
         * 与127.0.0.1建立长连接。 
         */
       future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8080));
    }
    
    /**
     * 发送消息至server
     */
    public void sendMsg()
    {
        if(future==null) return;
        String s = "Hello Word!";
        future.getChannel().write(s);
    }
    
}


2、Handler.java

  1. package HelloWord;  
  2.   
  3. import org.jboss.netty.channel.ChannelHandlerContext;  
  4. import org.jboss.netty.channel.ExceptionEvent;  
  5. import org.jboss.netty.channel.MessageEvent;  
  6. import org.jboss.netty.channel.SimpleChannelUpstreamHandler;  
  7.   
  8. /** 
  9.  * client和server接收消息共用的handler 
  10.  * 由于两个都是继承自SimpleChannelUpstreamHandler,所以就写在一起了。 
  11.  * @author Ransom 
  12.  * 
  13.  */  
  14. public class Handler extends SimpleChannelUpstreamHandler  
  15. {  
  16.     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)  
  17.             throws Exception  
  18.     {  
  19.         System.out.println("recive message,message content:"+e.getMessage());  
  20.           
  21.     }  
  22.       
  23.     public void exceptionCaught(  
  24.             ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {  
  25.         System.err.println("Client has a error,Error cause:"+e.getCause());  
  26.         e.getChannel().close();  
  27.     }  
  28. }  
package HelloWord;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * client和server接收消息共用的handler
 * 由于两个都是继承自SimpleChannelUpstreamHandler,所以就写在一起了。
 * @author Ransom
 *
 */
public class Handler extends SimpleChannelUpstreamHandler
{
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
            throws Exception
    {
        System.out.println("recive message,message content:"+e.getMessage());
        
    }
    
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.err.println("Client has a error,Error cause:"+e.getCause());
        e.getChannel().close();
    }
}


3、Server.java

  1. package HelloWord;  
  2.   
  3. import static org.jboss.netty.channel.Channels.pipeline;  
  4.   
  5. import java.net.InetSocketAddress;  
  6. import java.util.concurrent.Executors;  
  7.   
  8. import org.jboss.netty.bootstrap.ServerBootstrap;  
  9. import org.jboss.netty.channel.ChannelPipeline;  
  10. import org.jboss.netty.channel.ChannelPipelineFactory;  
  11. import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;  
  12. import org.jboss.netty.handler.codec.string.StringDecoder;  
  13. import org.jboss.netty.handler.codec.string.StringEncoder;  
  14.   
  15. /** 
  16.  * 在本地8080端口启动netty服务 
  17.  * @author Ransom 
  18.  * 
  19.  */  
  20. public class Server  
  21. {  
  22.     public static void main(String[] args)  
  23.     {  
  24.        /* 
  25.         * server的注释和client类似,在这里就不重复了 
  26.         * 但是需要注意的是server初始化的是ServerBootstrap的实例 
  27.         * client初始化的是ClientBootstrap,两个是不一样的。 
  28.         * 里面的channelfactory也是NioServerSocketChannelFactory。 
  29.         */  
  30.           
  31.         ServerBootstrap bootstrap = new ServerBootstrap(  
  32.                 new NioServerSocketChannelFactory(  
  33.                         Executors.newCachedThreadPool(),  
  34.                         Executors.newCachedThreadPool()));  
  35.   
  36.         bootstrap.setPipelineFactory(new ChannelPipelineFactory()  
  37.         {  
  38.   
  39.             @Override  
  40.             public ChannelPipeline getPipeline() throws Exception  
  41.             {  
  42.                 ChannelPipeline pipleline = pipeline();  
  43.                 pipleline.addLast("encode"new StringEncoder());  
  44.                 pipleline.addLast("decode"new StringDecoder());  
  45.                 pipleline.addLast("handler"new Handler());  
  46.                 return pipleline;  
  47.             }  
  48.   
  49.         });  
  50.           
  51.         bootstrap.bind(new InetSocketAddress(8080));  
  52.     }  
  53. }  
package HelloWord;

import static org.jboss.netty.channel.Channels.pipeline;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * 在本地8080端口启动netty服务
 * @author Ransom
 *
 */
public class Server
{
    public static void main(String[] args)
    {
       /*
        * server的注释和client类似,在这里就不重复了
        * 但是需要注意的是server初始化的是ServerBootstrap的实例
        * client初始化的是ClientBootstrap,两个是不一样的。
        * 里面的channelfactory也是NioServerSocketChannelFactory。
        */
        
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        bootstrap.setPipelineFactory(new ChannelPipelineFactory()
        {

            @Override
            public ChannelPipeline getPipeline() throws Exception
            {
                ChannelPipeline pipleline = pipeline();
                pipleline.addLast("encode", new StringEncoder());
                pipleline.addLast("decode", new StringDecoder());
                pipleline.addLast("handler", new Handler());
                return pipleline;
            }

        });
        
        bootstrap.bind(new InetSocketAddress(8080));
    }
}


4、HelloWordMain.java

  1. package HelloWord;  
  2. /** 
  3.  * Netty 初步之hello word的client入口 
  4.  * @author Ransom 
  5.  * 
  6.  */  
  7. public class HelloWordMain  
  8. {  
  9.     public static void main(String[] args)  
  10.     {  
  11.         ClientThread r = new ClientThread();  
  12.         Thread t = new Thread(r);  
  13.         t.setName("client thread");  
  14.         t.start();  
  15.           
  16.         while(true)  
  17.         {  
  18.             try  
  19.             {  
  20.                 Thread.sleep(3000);  
  21.             } catch (InterruptedException e)  
  22.             {  
  23.                 // TODO Auto-generated catch block   
  24.                 e.printStackTrace();  
  25.             }  
  26.             r.sendMsg();  
  27.         }  
  28.          
  29.     }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics