Netty(2)

59 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情

public class NettyServer {
    public static void main(String[] args) {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    protected void initChannel(NioSocketChannel ch) {
                    }
                });

        serverBootstrap.bind(8000);
    }
}

来看这样一段代码。

boosGroup是用来监听accept新连接的线程组,workGrop是用来处理新连接的线程组。

引导类 ServerBootstrap,这个类将引导我们进行服务端的启动工作,直接new出来开搞

通过group注册上面2个Group类

channel则是指定IO模型

需要线程模型(boosGroup,workersGroup)、IO 模型(NioServerSocketChannel),以及 IO 业务处理逻辑(initChannel方法中的逻辑)三大参数

客户端启动流程

public class NettyClient {
    public static void main(String[] args) {
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        
        Bootstrap bootstrap = new Bootstrap();
        bootstrap
                // 1.指定线程模型
                .group(workerGroup)
                // 2.指定 IO 类型为 NIO
                .channel(NioSocketChannel.class)
                // 3.IO 处理逻辑
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) {
                    }
                });
        // 4.建立连接
        bootstrap.connect("juejin.cn", 80).addListener(future -> {
            if (future.isSuccess()) {
                System.out.println("连接成功!");
            } else {
                System.err.println("连接失败!");
            }

        });
    }
}

差不多,也是需要线程模型(boosGroup,workersGroup)、IO 模型(NioServerSocketChannel),以及 IO 业务处理逻辑(initChannel方法中的逻辑)三大参数

客户端和服务端实现双向通信

建立连接的话需要重写channelActive方法,回复消息的话需要重写channelRead方法

具体代码实现可看demo

数据传输载体ByteBuffer介绍

感觉跟计算机网络的滑动窗口有点像

读字节时读指针向右移动一格,写字节时写指针向右移动一格,还会维护capacity,如果写指针写道capacity时,就不能再写了,而是需要先判断capacity是否小于maxCapacity,小于的话就先进行扩容

API

上面2个代码的作用是一样的,都是可以在进行一些读操作后进行反复读取,推荐方式2,方式1会自己定义变量,不太友好,写操作也是一样的,那么在我们进行了上述的操作后,就可以对一些数据进行反复读取了

Netty使用到的内存需要我们手动回收

release() 与 retain()

原理跟可重入锁差不多,当创建完一个 ByteBuf,它的引用为1,调用一次retain(),引用+1,调用一次release(),引用-1,当引用为0时,自动回收