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

Netty写的Echo 服务器的例子

1. Netty写的Echo服务器

  1. 项目结构与依赖
    • 确保已经正确设置了开发环境,包括JDK、IDE和Apache Maven。
    • 在Maven项目中,需要添加Netty的依赖,以下是一个简单的POM配置示例:
      <dependencies>
          <dependency>
              <groupId>io.netty</groupId>
              <artifactId>netty-all</artifactId>
              <version>4.1.90.Final</version> <!-- 请根据实际版本号修改 -->
          </dependency>
      </dependencies>
      
  2. 服务器代码实现
    • 创建EchoServerHandler类
      import io.netty.buffer.ByteBuf;
      import io.netty.channel.ChannelHandlerContext;
      import io.netty.channel.ChannelInboundHandlerAdapter;
      
      public class EchoServerHandler extends ChannelInboundHandlerAdapter {
          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) {
              // 处理接收到的消息
              ByteBuf in = (ByteBuf) msg;
              System.out.println("Server received: " + in.toString(io.netty.util.CharsetUtil.UTF_8));
      
              // 将接收到的消息写回给客户端
              ctx.write(in);
          }
      
          @Override
          public void channelReadComplete(ChannelHandlerContext ctx) {
              // 当所有数据都被读取完成后,刷新缓冲区并关闭连接
              ctx.writeAndFlush(io.netty.buffer.Unpooled.EMPTY_BUFFER)
                    .addListener(ChannelFutureListener.CLOSE);
          }
      
          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
              // 处理异常
              cause.printStackTrace();
              ctx.close();
          }
      }
      
      • channelRead方法:当从客户端接收到消息时,会调用这个方法。它将接收到的消息转换为ByteBuf对象,并打印出来。然后,将消息写回给客户端。
      • channelReadComplete方法:当所有数据都被读取完成后,会调用这个方法。它使用writeAndFlush方法将一个空的ByteBuf写回给客户端,并添加一个ChannelFutureListener,当写操作完成后,关闭连接。
      • exceptionCaught方法:当在处理过程中发生异常时,会调用这个方法。它打印异常的堆栈跟踪信息,并关闭连接。
    • 创建EchoServer类
      import io.netty.bootstrap.ServerBootstrap;
      import io.netty.channel.ChannelFuture;
      import io.netty.channel.EventLoopGroup;
      import io.netty.channel.nio.NioEventLoopGroup;
      import io.netty.channel.socket.nio.NioServerSocketChannel;
      
      public class EchoServer {
          private final int port;
      
          public EchoServer(int port) {
              this.port = port;
          }
      
          public static void main(String[] args) throws Exception {
              if (args.length!= 1) {
                  System.err.println("Usage: EchoServer <port>");
                  System.exit(1);
              }
      
              int port = Integer.parseInt(args[0]);
              new EchoServer(port).start();
          }
      
          public void start() throws Exception {
              // 创建EventLoopGroup,用于处理网络事件
              EventLoopGroup group = new NioEventLoopGroup();
              try {
                  // 创建ServerBootstrap,用于引导服务器启动
                  ServerBootstrap bootstrap = new ServerBootstrap();
                  bootstrap.group(group)
                        .channel(NioServerSocketChannel.class)
                        .localAddress(new io.netty.socket.InetSocketAddress(port))
                        .childHandler(new ChannelInitializer<io.netty.channel.socket.nio.SocketChannel>() {
                              @Override
                              protected void initChannel(io.netty.channel.socket.nio.SocketChannel ch) throws Exception {
                                  // 将EchoServerHandler添加到ChannelPipeline中
                                  ch.pipeline().addLast(new EchoServerHandler());
                              }
                          });
      
                  // 绑定服务器,并等待绑定完成
                  ChannelFuture future = bootstrap.bind().sync();
      
                  // 等待服务器关闭
                  future.channel().closeFuture().sync();
              } finally {
                  // 关闭EventLoopGroup,释放资源
                  group.shutdownGracefully().sync();
              }
          }
      }
      
      • 构造函数:初始化Echo服务器,指定服务器要监听的端口。
      • main方法:程序的入口点,解析命令行参数,创建EchoServer实例,并调用start方法启动服务器。
      • start方法
        • 创建EventLoopGroup:使用NioEventLoopGroup创建一个事件循环组,用于处理网络事件。
        • 创建ServerBootstrap:使用ServerBootstrap引导服务器启动,设置事件循环组、Channel类型和本地地址。
        • 设置ChildHandler:通过childHandler方法设置一个ChannelInitializer,用于初始化每个新连接的ChannelPipeline。在initChannel方法中,将EchoServerHandler添加到ChannelPipeline中,以处理客户端的消息。
        • 绑定服务器并等待完成:使用bind方法绑定服务器到指定的端口,并使用sync方法阻塞当前线程,直到绑定完成。
        • 等待服务器关闭:通过future.channel().closeFuture().sync()方法等待服务器关闭,当服务器的Channel关闭时,这个Future会完成。
        • 关闭EventLoopGroup:在服务器关闭后,使用group.shutdownGracefully().sync()方法关闭EventLoopGroup,释放资源。
  3. 运行示例
    • 编译和运行代码:可以使用Maven命令mvn clean package编译项目,然后使用java -jar target/echo-server-1.0-SNAPSHOT.jar <port>运行服务器,其中<port>是服务器要监听的端口号。
    • 测试功能:可以使用Netty提供的Telnet客户端或者其他网络工具来连接到服务器,并发送一些消息。服务器会接收到这些消息,并将它们回送给客户端。

以下是一个使用Telnet客户端测试Echo服务器的示例:

  • 打开终端
    • 在命令行中输入telnet localhost <port>,其中<port>是服务器监听的端口号。
  • 发送消息
    • 连接成功后,可以在终端中输入一些消息,然后按下回车键。服务器会接收到这些消息,并将它们回送给客户端。
  • 关闭连接
    • 在终端中输入quit命令,然后按下回车键,关闭与服务器的连接。

通过以上步骤,就可以使用Netty实现一个简单的Echo服务器,并进行测试。这个例子展示了Netty的基本使用方法,包括如何创建服务器、处理客户端连接和消息、以及如何关闭服务器。

2. 服务器端组件使用

2.1 EventLoopGroup
  • 创建:在EchoServer类的start方法中,使用NioEventLoopGroup创建一个事件循环组,用于处理网络事件。
EventLoopGroup group = new NioEventLoopGroup();
  • 作用:它是Netty的核心组件之一,用于处理网络连接的接受、数据的读取和写入等I/O操作。一个NioEventLoopGroup包含一个或多个NioEventLoop,每个NioEventLoop都有自己的线程,可以并发地处理多个网络连接。
2.2 ServerBootstrap
  • 创建与配置:在start方法中创建ServerBootstrap实例,并进行一系列配置。
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(group)
     .channel(io.netty.channel.nio.NioServerSocketChannel.class)
     .localAddress(new io.netty.socket.InetSocketAddress(port))
     .childHandler(new ChannelInitializer<io.netty.channel.socket.nio.SocketChannel>() {
            @Override
            protected void initChannel(io.netty.channel.socket.nio.SocketChannel ch) throws Exception {
                // 将EchoServerHandler添加到ChannelPipeline中
                ch.pipeline().addLast(new EchoServerHandler());
            }
        });
  • group方法:设置用于处理服务器端套接字的EventLoopGroup
  • channel方法:指定服务器使用的Channel类型,这里使用NioServerSocketChannel,它是基于NIO的服务器套接字通道实现。
  • localAddress方法:设置服务器要监听的本地地址和端口。
  • childHandler方法:设置一个ChannelInitializer,用于初始化每个新连接的SocketChannel。在initChannel方法中,将自定义的EchoServerHandler添加到ChannelPipeline中。
2.3 ChannelPipeline与ChannelHandler
  • ChannelPipeline:它是一个处理管道,用于组织和处理流经Channel的数据。当数据在Channel中流动时,会依次经过ChannelPipeline中的各个ChannelHandler
  • ChannelHandler:在这个例子中,自定义了EchoServerHandler类,它继承自ChannelInboundHandlerAdapter,用于处理客户端连接的入站数据。
    • channelRead方法:当从客户端接收到消息时,会调用这个方法。它将接收到的消息转换为ByteBuf对象,并打印出来,然后将消息写回给客户端。
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        System.out.println("Server received: " + in.toString(io.netty.util.CharsetUtil.UTF_8));
        ctx.write(in);
    }
    
    • channelReadComplete方法:当所有数据都被读取完成后,会调用这个方法。它使用writeAndFlush方法将一个空的ByteBuf写回给客户端,并添加一个ChannelFutureListener,当写操作完成后,关闭连接。
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(io.netty.buffer.Unpooled.EMPTY_BUFFER)
             .addListener(ChannelFutureListener.CLOSE);
    }
    
    • exceptionCaught方法:当在处理过程中发生异常时,会调用这个方法。它打印异常的堆栈跟踪信息,并关闭连接。
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
    

3. 启动与关闭服务器

  • 启动服务器:在start方法中,使用bind方法绑定服务器到指定的端口,并使用sync方法阻塞当前线程,直到绑定完成。
ChannelFuture future = bootstrap.bind().sync();
  • 等待服务器关闭:通过future.channel().closeFuture().sync()方法等待服务器关闭,当服务器的Channel关闭时,这个Future会完成。
  • 关闭EventLoopGroup:在服务器关闭后,使用group.shutdownGracefully().sync()方法关闭EventLoopGroup,释放资源。

http://www.kler.cn/news/342493.html

相关文章:

  • 美团Java一面
  • 【STM32单片机_(HAL库)】4-5-2【定时器TIM】【感应开关盖垃圾桶项目】HC-SR04超声波模块实验
  • 作为一名测试工程师如何学习Kubernetes(k8s)技能
  • Cherno游戏引擎笔记(61~72)
  • 四、Spring Boot集成Spring Security之认证流程
  • 鸿蒙NEXT开发-沉浸式导航和键盘避让模式(基于最新api12稳定版)
  • 音视频入门基础:FLV专题(14)——FFmpeg源码中,解码Script Tag的实现
  • Android常用C++特性之std::make_pair
  • 《动手学深度学习》Pytorch 版学习笔记一:从预备知识到现代卷积神经网络
  • 学习 JpGraph-历史曲线
  • 五种IO(输入/输出)模型
  • 微服务发展历程
  • 本地部署Docsify生成文档网站并实现公网环境远程访问
  • 机器学习与神经网络:从研究工具到诺贝尔物理学奖的突破
  • flutter鸿蒙版本通过底部导航栏的实现熟悉架构及语法
  • Docker 的数据管理
  • EdgeNAT: 高效边缘检测的 Transformer
  • MySQL(B站CodeWithMosh)——2024.10.10(13)
  • adum1201数字隔离器中文资料与应用
  • TY1801 内置GaN电源芯片(18w-65w)