学习一门技术,都是从简单的实例一步一步开始认识起来的,今天就来netty的第一个简单的实例。
TcpClient
/**
* @FileName: TcpClient.java
* @Package:Netty4.example
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:13:15
* @version V1.0
*/
package Netty4.zhanbao;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* @ClassName: TcpClient
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:13:15
*/
public class TcpClient {
public static String HOST = "localhost";
public static int PORT = 9999;
public static void connect(String host, int port) {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
try {
b.group(group).channel(NioSocketChannel.class);
b.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("handler", new TcpClientHandler());
}
});
// 设置tcp的参数信息
b.option(ChannelOption.SO_KEEPALIVE, true);
b.option(ChannelOption.TCP_NODELAY, true);
// 建立连接操作,同步建立连接请求
ChannelFuture channelFuture = b.connect(host, port).sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
connect(HOST, PORT);
}
}
TcpClientHandler
/**
* @FileName: TcpClientHandler.java
* @Package:Netty4.example
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:35:32
* @version V1.0
*/
package Netty4.zhanbao;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.MessageToByteEncoder;
/**
* @ClassName: TcpClientHandler
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:35:32
*/
public class TcpClientHandler extends ChannelInboundHandlerAdapter {
private int counter;
private byte[] req;
public TcpClientHandler() {
req = ("QUERY TIME ORDER" + System.getProperty("line.separator"))
.getBytes();
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 循环发送100条消息
ByteBuf message = null;
for (int i = 0; i < 100; i++) {
message = Unpooled.buffer(req.length);
message.writeBytes(req);
ctx.writeAndFlush(message);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("Now is:" + body + "; the counter is:" + ++counter);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("我已经读取完毕了");
ctx.channel().close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
}
}
TcpServer
/**
* @FileName: TcpServer.java
* @Package:Netty4.example
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:37:26
* @version V1.0
*/
package Netty4.zhanbao;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
/**
* @ClassName: TcpServer
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:37:26
*/
public class TcpServer {
private static final String IP = "localhost";
private static final int PORT = 9999;
/* 用于分配处理业务线程的线程组个数 */
protected static final int BIZGROUPSIZE = Runtime.getRuntime()
.availableProcessors() * 2;
/* 业务出现线程大小 */
protected static final int BIZTHREADSIZE = 4;
/*
* NioEventLoopGroup实际上就是个线程池,
* NioEventLoopGroup在后台启动了n个NioEventLoop来处理Channel事件,
* 每一个NioEventLoop负责处理m个Channel,
* NioEventLoopGroup从NioEventLoop数组里挨个取出NioEventLoop来处理Channel
*/
protected static void connect() throws Exception {
ServerBootstrap b = new ServerBootstrap();
EventLoopGroup bossGroup = new NioEventLoopGroup(BIZGROUPSIZE);
EventLoopGroup workerGroup = new NioEventLoopGroup(BIZTHREADSIZE);
try {
b.group(bossGroup, workerGroup);
b.channel(NioServerSocketChannel.class).option(
ChannelOption.TCP_NODELAY, true);
b.childHandler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new TcpServerHandler());
}
});
ChannelFuture channelFuture = b.bind(IP, PORT).sync();
System.out.println("TCP服务器已经启动");
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
connect();
System.out.println("服务端已经启动");
}
}
TcpServerHandler
/**
* @FileName: TcpServerHandler.java
* @Package:Netty4.example
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:47:19
* @version V1.0
*/
package Netty4.zhanbao;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
* @ClassName: TcpServerHandler
* @Description:
* @author: LUCKY
* @date:2016年4月12日 下午3:47:19
*/
public class TcpServerHandler extends ChannelInboundHandlerAdapter{
private int Counter;
/*建立连接时的操作*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//由于加入了StringDecoder,所以直接就是String
ByteBuf buf=(ByteBuf) msg;
byte[] req=new byte[buf.readableBytes()];
buf.readBytes(req);
System.out.println(new String(req));
String body=new String(req, "UTF-8").substring(0, req.length-System.getProperty("line.separator").length());
System.out.println("The time Server receive order:"+body+"; the Counter is :"+ ++Counter);
String currentTime="QUERY TIME ORDER".equalsIgnoreCase(body)? new java.util.Date(System.currentTimeMillis()).toString():"BAD ORDER";
currentTime=currentTime+System.getProperty("line.separator");
ByteBuf resp=Unpooled.copiedBuffer(currentTime.getBytes());
ctx.write(resp);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//当服务端关闭时,仍会走该方法
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
Netty是通过事件模型驱动,每一个时间都是在handler中进行流转的,后面会陆续的介绍。