Netty学习总结

目录

一、Netty是什么呢?

1.1什么是同步、什么是异步?

1.2什么是基于事件驱动?

1.3什么是IO、什么是NIO?

二、自定义一个Netty服务端与客户端

三、什么是TCP的粘包和拆包?如何解决?

使用Netty自带的解码器:


一、Netty是什么呢?

Netty是一个异步基于事件驱动的网络应用框架,用以快速开发高性能,高可靠的网络IO程序。其本质只一个NIO的框架,主要针对于TCP协议。

1.1什么是同步、什么是异步?

同步:指一个进程在执行某条请求时,需要获取到需要的数据之后,才能继续执行之后的操作。(在等待的这段时间内,该进程一直等待阻塞)

异步:指一条指令在执行某条请求时,如需要获取数据该请求不需要一直等待,而是先去执行后续的操作,等到消息体返回时,系统会通知进程进行处理。这样大大提高了效率。

1.2什么是基于事件驱动?

  1. 事件:在Netty中,事件是指各种网络操作的触发器,比如连接建立、数据读取和写入等。事件可以是系统产生的,也可以是外部输入的。
  2. 事件源:事件源是产生事件的实体,可以是客户端、服务端、连接、通道等。事件源负责触发事件并把事件传递给事件处理器。
  3. 事件处理器:事件处理器是对特定事件的处理逻辑的封装。当一个事件被触发,事件处理器负责执行相应的业务逻辑。
  4. 事件循环:事件循环是Netty的核心机制之一,负责将事件分发给相应的事件处理器进行处理。事件循环会不断地从事件队列中获取事件,并将事件分发给注册了该事件的事件处理器。
  5.  回调:Netty使用回调机制来实现事件的异步处理。当事件被处理完成后,会调用相应的回调方法,通知发起调用的代码。

Netty的事件驱动模型在底层利用了Java的NIO(New I/O)机制,通过选择器(Selector)监听通道上的不同事件,并进行相应的处理。

1.3什么是IO、什么是NIO?

IO(Input/Output)的缩写是计算机或者程序一外部世界交互的一种方式。

传统的IO模型是阻塞的。当执行数据的读写操作,程序都会进行阻塞等待读写操作完成之后才能进行后续操作;并且这种模型在处理大量并发连接时效率低下。

NIO是Java提供的一种基于通道缓冲区的IO模型。可以实现连接多个IO请求。

通道类似于IO中的流,但通道可以同时连接IO请求、实现异步非阻塞操作;

缓冲区直接在内存中进行数据的操作,减少了数据的拷贝。

二、自定义一个Netty服务端与客户端

服务端:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;


public class SomeServer {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup parentGroup = new NioEventLoopGroup();//处理客户端连接请求
        EventLoopGroup childGroup = new NioEventLoopGroup();//处理客户端服务请求

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap
                    //给引导类配置两大线程组
                    .group(parentGroup, childGroup)
                    //设置Channel(通道)的类型为NIO
                    .channel(NioServerSocketChannel.class)
                    // 设置连接配置参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    /**
                     * 配置通道事件的处理器
                     *
                     * 注:handler()与childHandler()方法的区别
                     */
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            /**
                             * 配置通道处理器:如编解码器、自定义处理器
                             */
                            pipeline.addLast(new HttpServerCodec());
                            pipeline.addLast(new SomeServerHandler());
                        }
                    });
            /**
             * sync()方法是一个用于将异步操作转换为同步操作的方法
             */
            ChannelFuture future = bootstrap.bind(8888).sync();
            System.out.println("服务端启动成功:端口8888");
            
            future.channel().closeFuture().sync();

        } finally {
            parentGroup.shutdownGracefully();
            childGroup.shutdownGracefully();
        }
    }
}
注:sync()方法

是ChannelFuture接口提供的一个同步方法。它用于将异步操作转换为同步操作,即等待操作完成并阻塞当前线程,直到操作完成或者发生异常。
当调用Netty中的一些异步操作方法时,通常会返回一个ChannelFuture对象,这个对象代表了未来可能发生的某个事件(如连接建立、消息发送等)。为了等待这个异步操作的结果,在需要同步等待的地方可以调用sync()方法。

使用sync()方法的代码会阻塞当前线程,直到对应的异步操作完成或发生异常。如果操作成功完成,即操作的状态为成功,sync()方法会立即返回。
如果操作发生异常,sync()方法会抛出对应的异常。

注:option()方法与childOption()方法区别

option()方法
1.用于配置服务器通道(ServerChannel)的一些选项。
2.可以设置一些影响服务器整体行为的参数,比如SO_BACKLOG(连接请求的最大队列长度)和SO_REUSEADDR(是否启用地址复用)等。
3.这些选项将应用于服务器监听Channel(通常是ServerSocketChannel)。

childOption()方法
1.用于配置每个客户端连接通道(Channel)的一些选项。
2.可以设置一些影响每个客户端连接行为的参数,比如TCP_NODELAY(是否启用Nagle算法)和SO_KEEPALIVE(是否开启TCP keep-alive)等。
3.这些选项将应用于每个客户端连接的Channel。

注:handler()与childHandler()方法的区别:
handler()方法
1.用于配置服务器通道(ServerChannel)的处理器,这个处理器是对整个服务器通道的处理逻辑。
2.该方法在服务端启动时被调用,并且只会被调用一次。
3.通常用于配置一些全局的处理器,例如日志、编解码器等,对于每个连接到服务器的客户端,这些处理器都是共享的。

childHandler()方法
1.用于配置每个客户端连接的通道(Channel)的处理器,这个处理器是对每个客户端连接的独立处理逻辑。
2.该方法在每个客户端连接被接受后被调用,并且会为每个客户端连接创建一个新的处理器实例。
3.通常用于配置客户端连接独有的处理器,例如业务逻辑处理器、请求解析器等。
4.每次有新的客户端连接接入时,都会自动调用childHandler()方法来创建新的处理器实例,并将该实例添加到客户端连接的通道中。

 客户端:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;


public class SomeClient {
    public static void main(String[] args) {
        NioEventLoopGroup loopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(loopGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new StringEncoder());
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect("localhost", 8888).sync();
            channelFuture.channel().closeFuture().sync();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            loopGroup.shutdownGracefully();
        }
    }
}

三、什么是TCP的粘包和拆包?如何解决?

粘包:发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

拆包:拆包问题是指接收端只收到了部分数据,而非完整的数据。

 解决办法:

使用Netty自带的解码器:

  • LineBasedFrameDecoder : 发送端发送数据包的时候,每个数据包之间以换行符作为分隔,LineBasedFrameDecoder 的工作原理是它依次遍历 ByteBuf 中的可读字节,判断是否有换行符,然后进行相应的截取。
  • DelimiterBasedFrameDecoder : 可以自定义分隔符解码器,LineBasedFrameDecoder 实际上是一种特殊的 DelimiterBasedFrameDecoder 解码器。
  • FixedLengthFrameDecoder: 固定长度解码器,它能够按照指定的长度对消息进行相应的拆包。
  • LengthFieldBasedFrameDecoder:按照指定长度分割。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值