代码大部分和上一篇《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();
}
}
}