当前位置:   article > 正文

Netty入门——springboot框架开发一个简单的服务器端和客户端_怎样使用springboot创建一个netty

怎样使用springboot创建一个netty

一、加入依赖

  • 加入依赖

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.39.Final</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

二、服务器端

2.1、服务器端代码

  • 服务器端代码

    package com.example.nettytest.netty.day1;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.logging.LoggingHandler;
    
    /**
     * @description:
     * @author: xz
     */
    public class Server {
        public static void main(String[] args) {
            //1、服务端启动器:负责组装netty组件
            new ServerBootstrap()
                //2、添加 EventLoop(事件循环)
                .group(new NioEventLoopGroup())
                //3、选择服务器的 ServerSocketChannel 实现
                .channel(NioServerSocketChannel.class)
                //4、添加服务端处理器
                // boss负责处理连接;worker(也就是netty中的child) 负责处理读写,决定了 worker(也就是netty中的child) 能执行哪些操作(handler)
                .childHandler(
                        // 5. channel 代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler
                        new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            //6、添加具体 handler
                            nioSocketChannel.pipeline().addLast(new LoggingHandler());
                            nioSocketChannel.pipeline().addLast(new StringDecoder());//将 ByteBuf 转换为字符串
                            nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){//自定义handler
                                //处理读事件
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    // 打印上一步转换好的字符串
                                    System.out.println("msg==========="+msg);
                                }
                            });
                        }
                })
                //7、绑定监听端口
                .bind(8080);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

2.2、服务器端代码解读

  • 代码1位置 :服务端启动器:负责组装netty组件

  • 代码2位置 :创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector 后面会详细展开;

  • 代码3位置:选择服务 Scoket 实现类,其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现,其它实现还有
    在这里插入图片描述

  • 代码4位置:为啥方法叫 childHandler,是接下来添加的处理器都是给 SocketChannel 用的,而不是给 ServerSocketChannel。ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;

  • 代码5位置:channel代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler;

  • 代码6位置:添加具体 handler;

  • 代码7位置: ServerSocketChannel 绑定的监听端口;

三、客户端

3.1、客户端代码

  • 客户端代码
package com.example.nettytest.netty.day1;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;

/**
 * @description:
 * @author: xz
 */
public class Client {
    public static void main(String[] args) throws InterruptedException {
        // 1. 客户端启动器
        new Bootstrap()
            // 2. 添加 EventLoop(事件循环)
            .group(new NioEventLoopGroup())
            // 3. 选择客户端的 SocketChannel 实现
            .channel(NioSocketChannel.class)
            // 4. 添加客户端处理器
            .handler(new ChannelInitializer<NioSocketChannel>() {
                // 在连接建立后被调用
                @Override
                protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                    //9. 消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出
                    nioSocketChannel.pipeline().addLast(new StringEncoder());
                }
            })
            .connect(new InetSocketAddress("localhost",8080))//5. 连接到服务器
            .sync()//6. 等待 connect 建立连接完毕
            .channel()//7. 连接对象
            .writeAndFlush("hello world !");//8. 发送数据
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

3.2、客户端代码解读

  • 代码1位置 :客户端启动器;
  • 代码2位置 :创建 NioEventLoopGroup(事件循环),同 Server服务端;
  • 代码3位置 :选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现,其它实现还有
    在这里插入图片描述
  • 代码4位置 :添加 SocketChannel 的处理器,ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;
  • 代码5位置 :指定要连接的服务器和端口;
  • 代码6位置 :Netty 中很多方法都是异步的,如 connect,这时需要使用 sync 方法等待 connect 建立连接完毕;
  • 代码7位置 :获取 channel 对象,它即为通道抽象,可以进行数据读写操作;
  • 代码8位置 :入消息并清空缓冲区;
  • 代码9位置 :消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出;
    数据经过网络传输,到达服务器端,服务器端 5 和 6 处的 handler 先后被触发,走完一个流程

四、服务端和客户端流程梳理

  • 流程梳理

    在这里插入图片描述

五、channel 、msg 、handler 和eventLoop 概念理解

5.1、channel 的理解

  • 把 channel 理解为数据的通道

5.2、msg 的理解

  • 把 msg 理解为流动的数据,最开始输入是 ByteBuf,但经过 pipeline 的加工,会变成其它类型对象,最后输出又变成 ByteBuf

5.3、handler 的理解

  • 把 handler 理解为数据的处理工序
    (1)、工序有多道,合在一起就是 pipeline,pipeline 负责发布事件(读、读取完成…)传播给每个 handler, handler 对自己感兴趣的事件进行处理(重写了相应事件处理方法);
    (2)、handler 分 Inbound 和 Outbound 两类;

5.4、eventLoop 的理解

  • 把 eventLoop 理解为处理数据的工人
    (1)、工人可以管理多个 channel 的 io 操作,并且一旦工人负责了某个 channel,就要负责到底(绑定);
    (2)、工人既可以执行 io 操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个 channel 的待处理任务,任务分为普通任务、定时任务;
    (3)、工人按照 pipeline 顺序,依次按照 handler 的规划(代码)处理数据,可以为每道工序指定不同的工人;
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号