当前位置: 首页 > article >正文

初识Netty(使用Netty实现服务端与客户端)

初识Netty(使用Netty实现服务端与客户端)

一、Netty简介

Netty 是基于 Java NIO 的异步事件驱动的网络应用框架,使用 Netty 可以快速开发网络应用,Netty 提供了高层次的抽象来简化 TCP 和 UDP 服务器的编程,但是你仍然可以使用底层的 API。

Netty 的内部实现是很复杂的,但是 Netty 提供了简单易用的API从网络处理代码中解耦业务逻辑。Netty 是完全基于 NIO 实现的,所以整个 Netty 都是异步的。

Netty 是最流行的 NIO 框架,它已经得到成百上千的商业、商用项目验证,许多框架和开源组件的底层 rpc 都是使用的 Netty,如 Dubbo、Elasticsearch 等等。下面是官网给出的一些 Netty 的特性:

设计方面

  • 对各种传输协议提供统一的 API(使用阻塞和非阻塞套接字时候使用的是同一个 API,只是需要设置的参数不一样)。
  • 基于一个灵活、可扩展的事件模型来实现关注点清晰分离。
  • 高度可定制的线程模型——单线程、一个或多个线程池。
  • 真正的无数据报套接字(UDP)的支持(since 3.1)。

易用性

  • 完善的 Javadoc 文档和示例代码。
  • 不需要额外的依赖,JDK 5 (Netty 3.x) 或者 JDK 6 (Netty 4.x) 已经足够。

性能

  • 更好的吞吐量,更低的等待延迟。
  • 更少的资源消耗。
  • 最小化不必要的内存拷贝。

安全性

  • 完整的 SSL/TLS 和 StartTLS 支持

二、一个简单的网络服务器

我这里使用的开发环境是idea+maven+netty4,pom中的maven依赖的版本是

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.0.33.Final</version>
</dependency>
服务端代码
public class NettyMsgServer {
    public static void getMsg() throws InterruptedException {
        ServerBootstrap bootstrap = new ServerBootstrap();
      
        EventLoopGroup mainEventLoopGroup = new NioEventLoopGroup(1);
      
        EventLoopGroup subEventLoopGroup = new NioEventLoopGroup(2);
        
        bootstrap.group(mainEventLoopGroup, subEventLoopGroup);
      
        bootstrap.channel(NioServerSocketChannel.class);
       
        bootstrap.localAddress(17777);
       
        bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);

        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel channel) throws Exception {
                channel.pipeline().addLast(new NettyMsgServerHandler());
                
            }
        });
     
        ChannelFuture channelFuture = bootstrap.bind().sync();
        System.out.println("Netty服务器启动成功,监听链接....");

        ChannelFuture closeFuture = channelFuture.channel().closeFuture();
        closeFuture.sync();

        subEventLoopGroup.shutdownGracefully();
        mainEventLoopGroup.shutdownGracefully();
    }

    public static void main(String[] args) throws InterruptedException {
        getMsg();
    }
}
服务端消息处理Handler
// 我们是服务端,服务端是不是 进行消息的 接收啊,所以是in
public class NettyMsgServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //对接受到的消息进行处理
        ByteBuf in = (ByteBuf) msg;
        try {
            while (in.isReadable()) {
                System.out.print((char) in.readByte());
            }
            System.out.println();
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }
}

三、一个简单的用户端

用户端代码
public class NettyMsgCilent {
    public static void sendMsg() throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        //客户端,也是要接收服务端的返回值的,既然客户端需要接收服务端的消息,那么客户端也需要
        //知道io何时达到,也需要有selector进行io状态的轮询,因为一个 client可能链接好几个server
        //但是客户端只需要一个group就行了,不需要main的group,因为客户端的链接状态是 服务端进行创建的
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup(2);
        bootstrap.group(eventLoopGroup);
        //设置channel类型
        bootstrap.channel(NioSocketChannel.class);
        //绑定ip、 port
        bootstrap.remoteAddress("127.0.0.1", 17777);
        //参数设置
        bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        //pipeline和handler设置
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new NettyMsgCilentHandler());
            }
        });

        ChannelFuture channelFuture = bootstrap.connect();
        channelFuture.addListener((ChannelFuture listener) -> {
            if(listener.isSuccess()) {
                System.out.println("连接 成功!");
            } else {
                System.out.println("连接 失败! 可以进行后续的补救措施!");
            }
        });

        channelFuture.sync(); // 我们的网络编程,比如 聊天工具,客户端的 连接阻塞只影响 你
  
        Channel channel = channelFuture.channel();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入发送内容:");
        while(scanner.hasNext()) {
            String next = scanner.next();
            Date date = new Date();
            String pattern = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            String time = sdf.format(date);
            byte[] bytes = (time + ">>" + next).getBytes();
            ByteBuf buffer = channel.alloc().buffer();
            buffer.writeBytes(bytes);
            channel.writeAndFlush(buffer);
            System.out.println("消息发送完成!");
        }

        eventLoopGroup.shutdownGracefully();
    }

    public static void main(String[] args) throws InterruptedException {
        sendMsg();
    }
}
用户端消息处理handler
public class NettyMsgCilentHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("read!");
    }
}

四、实现效果

用户端

image-20250123115404497

服务端

image-20250123115428126


http://www.kler.cn/a/515864.html

相关文章:

  • 运算放大器应用电路设计笔记(六)
  • SpringBoot集成Flink-CDC,实现对数据库数据的监听
  • WPF 引发类型为“System.Windows.Forms.AxHost+InvalidActiveXStateException”的异常 解决办法
  • 全面解析计算机网络:从局域网基础到以太网交换机!!!
  • linux下使用脚本实现对进程的内存占用自动化监测
  • 使用Redis缓解数据库压力+三种常见问题
  • AWScurl笔记
  • 【Java设计模式-7】责任链模式:我是流水线的一员
  • No.37 笔记 | Python面向对象编程学习笔记:探索代码世界的奇妙之旅
  • 2.5英寸笔记本电脑机械硬盘拆解方法
  • vim查找如何忽略字母的大小写
  • Java算法——排序
  • PHP如何封装项目框架达到高可用、高性能、高并发
  • 嵌入式知识点总结 C/C++ 专题提升(七)-位操作
  • 精讲Python之turtle库(二):设置画笔颜色、回旋伞、变色回旋伞、黄色三角形、五角星,附源代码
  • python列表增加数据函数
  • flume和kafka整合 flume和kafka为什么一起用?
  • Redis数据库笔记——持久化机制
  • VScode+ESP-IDF搭建ESP32开发环境
  • 探索 LLM:从基础原理到 RAG 实现的深度解析
  • Spring注解篇:@PostMapping详解
  • MATLAB中regexptranslate函数用法
  • 主站集中式和分布式的配电自动化系统区别在哪里?各适用于什么场所?一文详解
  • 【YOLOv11改进[Backbone]】使用LSKNet替换Backbone | 用于遥感目标检测的大型选择性核网络 | 2023
  • plus.runtime.install在android10无效
  • 【番外篇】排列组合实现算法1(Java版)