作者:手机用户2602935245 | 来源:互联网 | 2023-09-12 14:19
一、Netty的原理分析图 二、使用Netty框架的简单实现(实现client和server的消息收发) (1)NettyServer1publicclassNettySe
一、Netty的原理分析图
![Netty框架的简单实现(客户端和服务端收发消息) Netty框架的简单实现(客户端和服务端收发消息)](https://img1.php1.cn/3cd4a/24ed6/339/07df6d8cf2b21f11.png)
![Netty框架的简单实现(客户端和服务端收发消息) Netty框架的简单实现(客户端和服务端收发消息)](https://img1.php1.cn/3cd4a/24ed6/339/db1f62c3868a9cc2.png)
二、使用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() {//(用内部类的方法)
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() {//创建一个通道初始化对象
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方法来处理的。