使用Netty进行网络间对象传输

代码大部分和上一篇《Netty初步之Hello World》一样,所以这里也就不写什么说明了,仅仅粘贴代码就OK了。
1、ClientThread.java

package ObjectTest;

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.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;

/**
 * 启动一个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 ObjectEncoder());
                pipleline.addLast("decode", new ObjectDecoder());
                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;
       People p = new People();
       p.setName("ransom");
       p.setAge("25");
        future.getChannel().write(p);
    }
    
}
2、Handler.java
package ObjectTest;

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
    {
        People p = (People) e.getMessage();
        System.out.println("recive message,message content:"+p.getName()+",age:"+p.getAge());
        
    }
    
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.err.println("Client has a error,Error cause:"+e.getCause());
        e.getChannel().close();
    }
}
3、People.java
package ObjectTest;

import java.io.Serializable;

public class People implements Serializable
{
    /**
     * 
     */
    private static final long serialVersionUID = -8443519314107050709L;
    private String name;
    private String age;
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getAge()
    {
        return age;
    }
    public void setAge(String age)
    {
        this.age = age;
    }
}
4、Server.java
package ObjectTest;

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.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;

/**
 * 在本地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 ObjectEncoder());
                pipleline.addLast("decode", new ObjectDecoder());
                pipleline.addLast("handler", new Handler());
                return pipleline;
            }

        });
        
        bootstrap.bind(new InetSocketAddress(8080));
        System.out.println("server start at 8080");

    }
}
5、TestMain.java
package ObjectTest;
/**
 * Netty 初步之hello word的client入口
 * @author Ransom
 *
 */
public class TestMain
{
    public static void main(String[] args)
    {
        ClientThread r = new ClientThread();
        Thread t = new Thread(r);
        t.setName("client thread");
        t.start();
        
        while(true)
        {
            try
            {
                Thread.sleep(3000);
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            r.sendMsg();
        }
       
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值