JS Bin

Netty框架的简单实现(客户端和服务端收发消息)

Netty框架的简单实现

一、Netty的原理分析图

 

 

 

 

 二、使用Netty框架的简单实现(实现client和server的消息收发)

   (1)NettyServer

 1 public class NettyServer {
 2     public static void main(String[] args) throws Exception{
 3         
 4          //创建两个线程池
 5          
 6         //创建一个线程组,接收客户端的连接
 7         EventLoopGroup bossGroup = new NioEventLoopGroup();
 8         //创建一个线程组,用于处理网络操作
 9         EventLoopGroup workerGroup = new NioEventLoopGroup();
10         //创建服务器端启动助手(用于配置参数)
11         ServerBootstrap serverBootstrap = new ServerBootstrap();
12         serverBootstrap.group(bossGroup,workerGroup)//设置两个线程组
13         .channel(NioServerSocketChannel.class)//精华部分,设置通道的底层实现,
14         //通过NioServerSocketChannel
15         //这也是Netty的与NIO搭配的地方(此处作为服务器端通道的实现)
16         .option(ChannelOption.SO_BACKLOG, 12)//设置线程队列中等待连接的个数
17         .childOption(ChannelOption.SO_KEEPALIVE, true)
18         //是否启用心跳保活机制。在双方TCP套接字建立连接后(即都进入ESTABLISHED状态)并
19          //且在两个小时左右
20          //上层没有任何数据传输的情况下,这套机制才会被激活。
21          * */
22         .childHandler(new ChannelInitializer<SocketChannel>() {//(用内部类的方法)
23         //创建一个通道初始化对象
24             public void initChannel(SocketChannel sc){
25                 sc.pipeline().addLast(new NettyServerHandler());//往pipeline链中添加
26                 //自定义的handler类
27             }
28         });
29         System.out.println("...Server is Ready...");
30         //ChannelFuture接口,用于在之后的某个时间点确定结果
31         ChannelFuture sf = serverBootstrap.bind(9999).sync();//绑定端口 非阻塞 异步
32         System.out.println("....Server is Start....");
33         //关闭通道,关闭线程组
34         sf.channel().closeFuture().sync();
35         bossGroup.shutdownGracefully();
36         workerGroup.shutdownGracefully();
37     }
38 }

  (2)NettyServerHandler

 1 //服务器中的业务处理类
 2 public class NettyServerHandler extends ChannelInboundHandlerAdapter {
 3 
 4     //数据读取事件
 5     public void channelRead(ChannelHandlerContext ctx,Object msg){
 6         //传来的消息包装成字节缓冲区
 7         ByteBuf byteBuf = (ByteBuf) msg;
 8         //Netty提供了字节缓冲区的toString方法,并且可以设置参数为编码格式:CharsetUtil.UTF_8
 9         System.out.println("客户端发来的消息:" + byteBuf.toString(CharsetUtil.UTF_8));
10     }
11 
12     //数据读取完毕事件
13     public void channelReadComplete(ChannelHandlerContext ctx){
14          //数据读取完毕,将信息包装成一个Buffer传递给下一个Handler,Unpooled.copiedBuffer会返回一个Buffer
15         //调用的是事件处理器的上下文对象的writeAndFlush方法
16         //意思就是说将  你好  传递给了下一个handler
17         ctx.writeAndFlush(Unpooled.copiedBuffer("你好!", CharsetUtil.UTF_8));
18     }
19 
20     //异常发生的事件
21     public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause){
22         //异常发生时关闭上下文对象
23         ctx.close();
24     }
25 }

  (3)NettyClient

 1 //网络客户端
 2 public class NettyClient {
 3     public static void main(String[] args) throws Exception{
 4         //创建一个线程组(不像服务端需要有连接等待的线程池)
 5         EventLoopGroup group = new NioEventLoopGroup();
 6         //创建客户端的服务启动助手完成相应配置
 7         Bootstrap b = new Bootstrap();
 8         b.group(group)
 9                 .channel(NioSocketChannel.class)
10                 .handler(new ChannelInitializer<SocketChannel>() {//创建一个通道初始化对象
11                     @Override
12                     protected void initChannel(SocketChannel socketChannel) throws Exception {
13                         socketChannel.pipeline().addLast(new NettyClientHandler());//往pipeline中添加自定义的handler
14                     }
15                 });
16         System.out.println("...Client is Ready...");
17         //启动客户端去连接服务器端(通过启动助手)
18         ChannelFuture cf = b.connect("127.0.0.1", 9999).sync();
19         //关闭连接(异步非阻塞)
20         cf.channel().closeFuture().sync();
21 
22     }
23 }

  (4)NettyClientHandler

 1 //客户端业务处理类
 2 public class NettyClientHandler extends ChannelInboundHandlerAdapter {
 3 
 4     //通道就绪事件(就是在bootstrap启动助手配置中addlast了handler之后就会触发此事件)
 5     //但我觉得也可能是当有客户端连接上后才为一次通道就绪
 6     public void channelActive(ChannelHandlerContext ctx){
 7         System.out.println("Client :" + ctx);
 8         //向服务器端发消息
 9         ctx.writeAndFlush(Unpooled.copiedBuffer("你好啊!", CharsetUtil.UTF_8));
10     }
11     //数据读取事件
12     public void channelRead(ChannelHandlerContext ctx,Object msg){
13         //传来的消息包装成字节缓冲区
14         ByteBuf byteBuf = (ByteBuf) msg;
15         //Netty提供了字节缓冲区的toString方法,并且可以设置参数为编码格式:CharsetUtil.UTF_8
16         System.out.println("服务器端发来的消息:" + byteBuf.toString(CharsetUtil.UTF_8));
17     }
18 
19 }

  通道的消息处理都是通过channelHandlerContext对象的writeAndFlush方法来处理的。

posted @ 2019-12-25 10:15  左五六  阅读(6218)  评论(0编辑  收藏  举报