官网
https://netty.io/downloads.html
Netty开发文档
https://netty.io/4.1/api/index.html
添加依赖
官网的依赖不能用,就到maven仓库搜索netty,选择io.netty,最新的一个
选择版本4
pom.xml
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.72.Final</version>
</dependency>
服务端
public class Server {
public static void main(String[] args) throws InterruptedException {
//创建两个事件循环组,bossGroup只处理连接请求,workGroup处理客户端业务处理,交给bossGroup
//两个都是无线循环
//默认CPU核*2
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
//创建服务端启动对象,配置参数
ServerBootstrap bootstrap = new ServerBootstrap();
//用链式编程进行设置
bootstrap.group(bossGroup, workGroup)//设置两个线程组
.channel(NioServerSocketChannel.class)//使用NioSocketChannel作为服务器通道实现
.option(ChannelOption.SO_BACKLOG, 128)//设置线程队列个数
.childOption(ChannelOption.SO_KEEPALIVE, true)//设置保持活动连接状态
.childHandler(new ChannelInitializer<SocketChannel>() {//创建通道测试对象(匿名对象)
//给pipeline设置处理器
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new ServerHandler());//向管道最后添加处理器
}
});//给workGroup的EventLoop对应的管道设置处理器
System.out.println("服务器准备好了");
//启动服务器,绑定端口,生成ChannelFuture对象
ChannelFuture future = bootstrap.bind(888).sync();
//对关闭通道进行监听(非阻塞监听,异步模型)
future.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
服务端处理器
public class ServerHandler extends ChannelInboundHandlerAdapter {
//当通道有读事件,会触发
//ChannelHandlerContext上下文,含有管道pipeline与通道channel
//Object msg 通道数据
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//System.out.println("server ctx:" + ctx);
//将msg转成ByteBuf
ByteBuf buf = (ByteBuf) msg;
System.out.println(buf.toString(CharsetUtil.UTF_8));
//System.out.println(ctx.channel().remoteAddress());
System.out.println("读到的线程 "+Thread.currentThread().getName());
}
//数据读取完毕
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//将数据写入缓冲区并刷新 write+flush
//对发送数据编码
ctx.writeAndFlush(Unpooled.copiedBuffer("服务端:您好", CharsetUtil.UTF_8));
}
//处理异常,关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
客户端
public class Client {
public static void main(String[] args) throws InterruptedException {
//客户端只需要一个事件循环组
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建客户端启动对象,配置参数
Bootstrap bootstrap = new Bootstrap();
//用链式编程进行设置
bootstrap.group(group)//设置事件循环组
.channel(NioSocketChannel.class)//设置客户端通道实现
.handler(new ChannelInitializer<SocketChannel>() {//创建通道测试对象(匿名对象)
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new ClientHandler());//向管道最后添加处理器
}
});//给workGroup的EventLoop对应的管道设置处理器
System.out.println("客户端准备好了");
//启动客户端,绑定端口,连接服务端
ChannelFuture future = bootstrap.connect("127.0.0.1", 888).sync();
//对关闭通道进行监听(非阻塞监听,异步模型)
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
客户端处理器
public class ClientHandler extends ChannelInboundHandlerAdapter {
//当通道有读事件,会触发
//ChannelHandlerContext上下文,含有管道pipeline与通道channel
//Object msg 通道数据
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//System.out.println("client ctx:" + ctx);
//将msg转成ByteBuf
ByteBuf buf = (ByteBuf) msg;
System.out.println(buf.toString(CharsetUtil.UTF_8));
//System.out.println(ctx.channel().remoteAddress());
}
//当通道就绪触发该方法
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//将数据写入缓冲区并刷新 write+flush
//对发送数据编码
ctx.writeAndFlush(Unpooled.copiedBuffer("客户端:您好", CharsetUtil.UTF_8));
}
//处理异常,关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
EventLoopGroup默认CPU核*2
本机cpu为4核,超过8后从1继续开始