netty介绍
Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
netty服务器简单代码的实现
首先编写服务端
package com.fr.server.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NIOServer {
public static void main(String[] args) throws InterruptedException {
//netty基于主从reactor模式所以第一个executor是reactor子线程池
EventLoopGroup executors=new NioEventLoopGroup();
//创建处理业务的工作线程池
EventLoopGroup workgroup=new NioEventLoopGroup();
try {
//创建服务
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(executors,workgroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,128)
.childOption(ChannelOption.SO_KEEPALIVE,true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//设置业务处理handler
socketChannel.pipeline().addLast(new NettyServerHandler());
}
});
System.out.println("服务器 is ready");
//绑定端口 同步处理
ChannelFuture cf=serverBootstrap.bind(6668).sync();
cf.channel().closeFuture().sync();
} finally {
executors.shutdownGracefully();
workgroup.shutdownGracefully();
}
}
}
编写服务端业务处理handler
package com.fr.server.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
//读取客户端发送的数据
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("ctx="+ctx);
ByteBuf buf=(ByteBuf)msg;
System.out.println(buf.toString(CharsetUtil.UTF_8));
System.out.println(ctx.channel().remoteAddress());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.channel().close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("hello",CharsetUtil.UTF_8));
}
}
编写客户端代码
package com.fr.server.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class NettyClient {
public static void main(String[] args) {
NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
Bootstrap bootstrap=new Bootstrap();
try {
bootstrap.group(eventExecutors)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new NettyClientHandler());
}
});
System.out.println("客户端ok");
ChannelFuture sync = bootstrap.connect("127.0.0.1", 6668).sync();
sync.channel().closeFuture().sync();
} catch (Exception e){
e.printStackTrace();
} finally{
eventExecutors.shutdownGracefully();
}
}
}
编写客户端业务处理handler
package com.fr.server.netty;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buff=(ByteBuf)msg;
System.out.println("服务器返回"+buff.toString(CharsetUtil.UTF_8));
System.out.println(ctx.channel().remoteAddress());
}
//通道就绪开启该方法
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("ctx="+ctx);
ctx.writeAndFlush(Unpooled.copiedBuffer("hello", CharsetUtil.UTF_8));
}
}
netty任务队列
接下来我们做一个设想,假如客户端发送的是一个大文件,或是一个业务非常耗时的请求,这时候我们就需要将该请求分发到work group 子线程去处理来实现异步处理请求。
将任务改为异步执行
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// System.out.println("ctx="+ctx);
// ByteBuf buf=(ByteBuf)msg;
// System.out.println(buf.toString(CharsetUtil.UTF_8));
// System.out.println(ctx.channel().remoteAddress());
ctx.channel().eventLoop().execute(()->{
try {
Thread.sleep(5*1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("休眠了5秒",CharsetUtil.UTF_8));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
定时任务
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// System.out.println("ctx="+ctx);
// ByteBuf buf=(ByteBuf)msg;
// System.out.println(buf.toString(CharsetUtil.UTF_8));
// System.out.println(ctx.channel().remoteAddress());
ctx.channel().eventLoop().execute(()->{
try {
Thread.sleep(5*1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("休眠了5秒",CharsetUtil.UTF_8));
} catch (InterruptedException e) {
e.printStackTrace();
}
});
ctx.channel().eventLoop().schedule(()->{
try {
Thread.sleep(2*1000);
ctx.writeAndFlush(Unpooled.copiedBuffer("休眠了2秒",CharsetUtil.UTF_8));
} catch (InterruptedException e) {
e.printStackTrace();
}
},5,TimeUnit.SECONDS);
}
Netty的异步模型
ChannelFuture cf=serverBootstrap.bind(6668).sync();
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess())
System.out.println("监听chengg");
else
System.out.println("失败");
}});
cf.channel().closeFuture().sync();