Netty简单的入门代码示例

 更新时间:2023年12月21日 10:34:30   作者:Colins~  
这篇文章主要介绍了Netty简单的入门代码示例,Netty 的内部实现是很复杂的,但是 Netty 提供了简单易用的API从网络处理代码中解耦业务逻辑,Netty 是完全基于 NIO 实现的,所以整个 Netty 都是异步的,需要的朋友可以参考下

前言

纯Java几种网络IO的开发步骤及示例,毫无疑问最好的就是NIO,这也是目前最主流的方式,但是这玩意编写复杂,拓展性也不强,在通信上方方面面都需要重写,这不是一般人能搞得定了,所以呀我们得会用框架呀,Netty就是这方面框架中的佼佼者!

基础示例入门

服务端

NettyServer.class

@Slf4j
public class NettyServer{
    //1.创建线程组  bossGroup:连接线程   workGroup:工作线程
    private final NioEventLoopGroup bossGroup = new NioEventLoopGroup();
    private final NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    public void serverStart() throws InterruptedException {
        try{
            // 服务端启动类
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 传入两个线程组
            bootstrap.group(bossGroup, workerGroup)
                    // 指定Channel 和NIO一样是采用Channel通道的方式通信 所以需要指定服务端通道
                    .channel(NioServerSocketChannel.class)
                    //使用指定的端口设置套接字地址
                    .localAddress(new InetSocketAddress(11111))
                    //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //设置数据处理器
                    .childHandler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            // 在管道中 添加数据处理类
                            channel.pipeline().addLast(new NettyServerTestHandler());
                        }
                    });
            // 同步等待成功
            ChannelFuture future = bootstrap.bind().sync();
            if (future.isSuccess()) {
                log.info("启动 Netty Server 成功");
            }
            //等待服务端监听端口关闭 链路关闭后main函数才会结束
            future.channel().closeFuture().sync();
        }finally {
            // 优雅的关闭 释放资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        new NettyServer().serverStart();
    }
}

看上去好多,感觉比NIO还麻烦?其实很方便的:

  1. 实例化一个服务端 ServerBootstrap ,这个NIO也一样,Netty帮我们封装了
  2. 设置两个线程组,一个处理客户端连接事件,一个处理连接后数据处理事件
  3. 指定服务端通道类型,并绑定地址
  4. 设置传输的一些配置参数(这里有很多可以设置,所以拓展性强)
  5. 设置数据处理器,这里实际是添加了一个数据处理管道,管道内可以有很多数据处理类,所以可以一层一层处理,可插拔式设计(类似拦截器链)
channel.pipeline() : 这就是管道
new NettyServerTestHandler() : 这个就是管道里的一个数据处理类
// 数据处理类可以有多个
  • 最后启动

ServerBootstrap 实例化后,都是采用建造者模式设置的,对于我们来说是非常的方便的,这里配置好后我们的重心就可以放在数据处理类上了

NettyServerTestHandler.class

NettyServerTestHandler 就是数据处理类,所有的方法都帮我们封装好了,我们不需要考虑其中调用的问题,方法是处理什么事件的,我们写对应的逻辑就好了,方法上的ChannelHandlerContext 可以理解为管道中所有数据处理类的纽带,比如拦截器链不也有么

@Slf4j
public class NettyServerTestHandler extends ChannelInboundHandlerAdapter {
    // 读取信息调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 和NIO一样有缓冲区 ByteBuf就是对ByteBuffer做了一层封装
        ByteBuf msg1 = (ByteBuf) msg;
        log.info("客户端信息:" + msg1.toString(CharsetUtil.UTF_8));
    }
    // 连接事件 连接成功调用
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        log.info(socketAddress + " 已连接");
        // 发送数据
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Client", CharsetUtil.UTF_8));
    }
    // 断开连接调用
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.channel().remoteAddress() + " 已断开连接");
    }
    // 读取信息完成事件  信息读取完成后调用
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
    // 异常处理  发生异常调用
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常后 关闭与客户端连接
        ctx.close();
    }
}

客户端

NettyClient.class

客户端启动和服务端几乎一致,只不过启动类成了Bootstrap ,而且我还加入了一个断连逻辑

@Slf4j
public class NettyClient  {
    private EventLoopGroup group = new NioEventLoopGroup();
    private int port=11111;
    private String host="127.0.0.1";
    public void start() throws InterruptedException {
        try{
            Bootstrap bootstrap = new Bootstrap();
            // 客户端不需要处理连接 所以一个线程组就够了
            bootstrap.group(group)
                    // 连接通道
                    .channel(NioSocketChannel.class)
                    .remoteAddress(host, port)
                    .option(ChannelOption.TCP_NODELAY, true)
                    // 数据处理
                    .handler(new ChannelInitializer<Channel>() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(new NettyClientTestHandler());
                        }
                    });
            ChannelFuture future = bootstrap.connect();
            //客户端断线重连逻辑
            future.addListener((ChannelFutureListener) future1 -> {
                if (future1.isSuccess()) {
                    log.info("连接Netty服务端成功");
                } else {
                    log.info("连接失败,进行断线重连");
                    future1.channel().eventLoop().schedule(() -> {
                        try {
                            start();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }, 20, TimeUnit.SECONDS);
                }
            });
            future.channel().closeFuture().sync();
        }catch (Exception e){
            log.info("服务端异常");
        }finally {
            group.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        new NettyClient().start();
    }
}

NettyClientTestHandler.class

数据处理类也是一样的

@Slf4j
public class NettyClientTestHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf msg1 = (ByteBuf) msg;
        log.info("服务端信息:" + msg1.toString(CharsetUtil.UTF_8));
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 连接上 就给服务端发送数据
        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Server", CharsetUtil.UTF_8));
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        log.info(socketAddress + " 已连接");
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info(ctx.channel().remoteAddress() + " 已断开连接");
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

到此这篇关于Netty简单的入门代码示例的文章就介绍到这了,更多相关Netty入门代码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringCloud的Hystrix简单介绍

    SpringCloud的Hystrix简单介绍

    这篇文章主要介绍了SpringCloud的Hystrix简单介绍,SpringCloud Hystrix是Netflix开源的一款容错框架,具备服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)等功能,同样具有自我保护能力,需要的朋友可以参考下
    2023-07-07
  • Java实例讲解注解的应用

    Java实例讲解注解的应用

    JAVA注解 Annotation(注解)是JDK1.5及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以‘@注解名’在代码中存在的
    2022-06-06
  • 解析整合mybatis-spring需要的maven依赖配置问题

    解析整合mybatis-spring需要的maven依赖配置问题

    这篇文章主要介绍了整合mybatis-spring需要的maven依赖配置问题,创建Maven项目,导入相关jar包,文中还给大家提到了,解决maven静态资源约定大于习惯问题,本文给大家介绍的非常详细,需要的朋友参考下吧
    2021-11-11
  • jOOQ串联字符串拒绝使用的原因实例

    jOOQ串联字符串拒绝使用的原因实例

    这篇文章主要为大家介绍了jOOQ串联字符串拒绝使用的原因实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • SpringCloudGateway使用Skywalking时日志打印traceId解析

    SpringCloudGateway使用Skywalking时日志打印traceId解析

    这篇文章主要为大家介绍了SpringCloudGateway使用Skywalking时日志打印traceId解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 利用SpringBoot和LiteFlow解锁复杂流程

    利用SpringBoot和LiteFlow解锁复杂流程

    随着业务的复杂化,企业需要更加高效、便捷地管理自己的业务流程,这就需要借助一些流程引擎实现,今天,我们就来介绍一种基于Java语言开发的轻量级工作流引擎——LiteFlow,以及如何在Spring Boot框架中集成它,从而提高企业的工作效率和开发效率
    2023-06-06
  • 利用Java和c语言写一个计算器

    利用Java和c语言写一个计算器

    这篇文章我们就来分享如何利用Java和c语言来写一个计算器,文章附有代码详细说明,感兴趣得小伙伴可以参考下面文章得具体内容
    2021-10-10
  • MyBatis-Plus 动态表名SQL解析器的实现

    MyBatis-Plus 动态表名SQL解析器的实现

    这篇文章主要介绍了MyBatis-Plus 动态表名SQL解析器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • MyEclipse到期破解代码分享

    MyEclipse到期破解代码分享

    前几天有个小伙伴咨询,使用的时候一直说myeclipse已过期,需要购买,如何解决?可以去网上搜搜注册码,但作为程序猿这么做简直太无趣,看看我们自己来解决这个问题
    2014-11-11
  • SpringBoot登录验证token拦截器的实现

    SpringBoot登录验证token拦截器的实现

    本文主要介绍了SpringBoot登录验证token拦截器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论