1. NettyServer端配置
javaIO==>NIO===>Netty
package com.example.demo; 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; public class Server { public static void main(String[] args) throws InterruptedException { //NettyServer端配置流程 //1. 创建boosgroup和workergroup //2. Bossgroup只是负责处理连接请求,真正和客户端处理业务会交给workergro8up完成 EventLoopGroup bossGroup =new NioEventLoopGroup(); EventLoopGroup workerGroup =new NioEventLoopGroup(); //3.配置启动参数, ServerBootstrap bootstrap = new ServerBootstrap(); //4.用链式编程来进行设置 bootstrap.group(bossGroup,workerGroup) //设置两个线程组 .channel(NioServerSocketChannel.class) //使用NioSokectChannel作为服务器的通道实现 .option(ChannelOption.SO_BACKLOG, 128) //设置线程队列到底连接个数 .childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态 .childHandler(new ChannelInitializer<SocketChannel>() { //创建一个通道测试对象(匿名对象) //给pipeline设置处理器 @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(null); } }) ;//给workergroup的Eventloop管道设置处理器 System.out.println("。。。。服务器已经准备好"); //5. 绑定一个端口病同步,生成一个channelFuture对象. // 启动服务器,并绑定端口. ChannelFuture cf = bootstrap.bind(6668).sync(); //6.对关闭通道进行监听 cf.channel().closeFuture().sync(); } }
package com.example.demo; 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; public class Server { public static void main(String[] args) throws InterruptedException { //NettyServer端配置流程 //1. 创建boosgroup和workergroup //2. Bossgroup只是负责处理连接请求,真正和客户端处理业务会交给workergro8up完成 EventLoopGroup bossGroup =new NioEventLoopGroup(); EventLoopGroup workerGroup =new NioEventLoopGroup(); try { //3.配置启动参数, ServerBootstrap bootstrap = new ServerBootstrap(); //4.用链式编程来进行设置 bootstrap.group(bossGroup,workerGroup) //设置两个线程组 .channel(NioServerSocketChannel.class) //使用NioSokectChannel作为服务器的通道实现 .option(ChannelOption.SO_BACKLOG, 128) //设置线程队列到底连接个数 .childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态 .childHandler(new ChannelInitializer<SocketChannel>() { //创建一个通道测试对象(匿名对象) //给pipeline设置处理器 @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyClientHandler()); } }) ;//给workergroup的Eventloop管道设置处理器 System.out.println("。。。。服务器已经准备好"); //5. 绑定一个端口病同步,生成一个channelFuture对象. // 启动服务器,并绑定端口. ChannelFuture cf = bootstrap.bind(6668).sync(); //6.对关闭通道进行监听 cf.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
2.ServerHandler
package com.example.demo; 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; //1. 我们自定义一个handler 需要继续netty规定好的某个handleradapter. //2. 这是我们的自定义一个handler,才能称之为一个handler public class ServerHandler extends ChannelInboundHandlerAdapter{ //读取客户端发送的消息. //1. channelhandlercontext ctx 上下文对象 ,含有管道pipline , 通道channel ,地址 //2. object msg :就是客户端发送的数据 ,默认是object @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("server ctx ="+ ctx); //将msg转成一个bytebuf //ByteBuf 是netty提供的,不是NIO的ByteBuffer ByteBuf buf =(ByteBuf) msg; System.out.println("客户端发送消息是"+ buf.toString(CharsetUtil.UTF_8)); System.out.println("客户端地址是"+ctx.channel().remoteAddress()); } //数据读取完毕 @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //将数据写入缓存,并刷新. //对发送的数据发送编码 ctx.writeAndFlush(Unpooled.copiedBuffer("hello, 客户端",CharsetUtil.UTF_8)); } //处理异常,一般是需要关闭通道. //最后,把handler加入到pipeline中. @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } }
3. Client
package com.example.demo; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; 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) throws Exception { // 客户端需要一个事件循环组 EventLoopGroup group = new NioEventLoopGroup(); try { // 创建客户端启动对象 // 注意客户端不是serverbootstrap 而是Bootstrap Bootstrap bootstrap = new Bootstrap(); // 设置相关参数 bootstrap.group(group)// 设置线程组 .channel(NioSocketChannel.class)// 设置客户端的实现类(反射) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyClientHandler()); // 加入自己的处理器 } }); System.out.println("客户端 ok "); // 启动客户端去连接服务器端 // 关于channelFuture 要分析,设计到netty的异步模型. ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync(); // 给关闭通道进行监听 channelFuture.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } }
4.ClientHandler
package com.example.demo; import java.nio.charset.Charset; 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 channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("client" + ctx); ctx.writeAndFlush(Unpooled.copiedBuffer("hello,server你好...... ",CharsetUtil.UTF_8)); } //当通道有读取事件的时候,会触发 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 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 { cause.printStackTrace(); ctx.close(); } }