使用netty实现一个tcp的echo服务器。
(1)导入netty 的jar
(2)在主文件中搭建框架
package com.xing.echoserver;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class DiscardServer {
public static void main(String[] args) throws Exception {
ChannelFactory factory =
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new DiscardServerHandler());//这里的DiscardServerHandler实现我们的逻辑,需要
}
});
bootstrap.setOption("child.tcpNoDelay", true);//设置连接的一些属性
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(1872));//设置本地端口
}
}
对于上面的代码大部分是框架性质的我们先不去深究,把有注释的几个地方搞清楚就够。
(3)在类中实现我们的业务逻辑。
package com.xing.echoserver;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
public class DiscardServerHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {//收到消息是怎么办
Channel ch = e.getChannel();//拿到连接
ch.write(e.getMessage());//将收到的消息写回连接
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
Channel ch = e.getChannel();
ch.close();
}
}
(4)下面我们实现另外一个服务器-Time服务端程序,他的功能要求在客户端连接过来后,server马上发送一个当前的时间值(int类型的数据),而且发送成功之后马上关闭连接。
这里我们要重写的方法就不是messageReceived了,而是chennelConnected.
package org.jboss.netty.example.time; public class TimeServerHandler extendsSimpleChannelHandler
{ @Override public void channelConnected(ChannelHandlerContext
ctx,ChannelStateEvent
e) {Channel
ch = e.getChannel();//注意这里的Channel我们要引用netty包下面的Channel,而不是NIO包里面的Channel,因为netty对NIO的实现进行了增强。ChannelBuffer
time =ChannelBuffers
.buffer(4);//ChannelBuffers是一个帮助类,为我们实现分配buffer的功能,我们要发送一个int所以申请buffer 的长度是4 time.writeInt((int) (System.currentTimeMillis() / 1000));ChannelFuture
f = ch.write(time);//这里我们不需要flip,因为这里是netty的世界,不是NIO的世界,在这里ChannelBuffer有read、write两个指针分别用于读、写,方便多了。而且这里我们返回一个ChannelFuture,我们这么做是为了实现异步调用。我们不能马上调用ch.close f.addListener(newChannelFutureListener
() {//这里是一个匿名内部类,在完成write操作之后,Netty框架会执行operationComplete方法里面的代码 public void operationComplete(ChannelFuture
future) {Channel
ch = future.getChannel(); ch.close(); } }); } @Override public void exceptionCaught(ChannelHandlerContext
ctx,ExceptionEvent
e) { e.getCause().printStackTrace(); e.getChannel().close(); } }
(5)Netty实现time 协议的客户端