Netty入门指引

简介: Netty入门指引

1. 背景

   如今,我们使用通用应用程序或库相互通信。例如,我们经常使用HTTP客户端库从Web服务器检索信息,并通过Web服务调用远程过程调用。但是,通用协议或其实现有时不能很好地扩展。就像我们不使用通用的HTTP服务器来交换大文件,电子邮件和近乎实时的消息(例如财务信息和多人游戏数据)一样。所需要的是专门用于特殊目的的高度优化的协议实现,甚至可能要设计和实现完全适合您的需求的全新协议。另一个不可避免的情况是,您必须处理旧的专有协议以确保与旧系统的互操作性。在这种情况下,重要的是我们可以在不牺牲最终应用程序的稳定性和性能的情况下,以多快的速度实现该协议。


2. 简介

   Netty项目提供一个异步事件驱动的网络应用程序框架和工具,以快速开发可维护的高性能和高可扩展性协议服务器和客户端。换句话说,Netty是一个NIO客户端服务器框架,可以快速轻松地开发网络应用程序,例如协议服务器和客户端。它简化了网络编程,例如TCP和UDP套接字服务器的开发。


3. 初试

   首先从一个discard服务开始:这是一个协议,它丢弃所有接收到的数据而没有任何响应。要实现DISCARD协议,唯一需要做的就是忽略所有接收到的数据。示例如下:

package io.netty.example.discard;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
 * Handles a server-side channel.
 */
public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1)
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
        // Discard the received data silently.
        ((ByteBuf) msg).release(); // (3)
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

   释义:

  • DiscardServerHandler扩展ChannelInboundHandlerAdapter,它是ChannelInboundHandler的实现。ChannelInboundHandler提供了可以覆盖的各种事件处理程序方法。
  • 示例重写了channelRead()事件处理程序方法。每当从客户端接收到新数据时,就使用接收到的消息来调用此方法。在此示例中,接收到的消息的类型为ByteBuf。
  • 为了实现DISCARD协议,处理程序必须忽略收到的消息。ByteBuf是一个引用计数的对象,必须通过release()方法显式释放它。
  • 通常,channelRead()处理程序方法的实现方式如下:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    try {
        // Do something with msg
    } finally {
        ReferenceCountUtil.release(msg);
    }
}
  • 当Netty由于I / O错误而引发异常时,或者由于处理事件时引发异常而由处理程序实现引发异常时,将使用Throwable调用exceptionCaught()事件处理程序方法。在大多数情况下,应该记录捕获到的异常,并在此处关闭其关联的通道,此方法的实现可能会有所不同,具体取决于要处理特殊情况时要采取的措施。例如,可以在关闭连接之前发送带有错误代码的响应消息。


   下面是一个完整的main()方法的服务端:

package io.netty.example.discard;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
 * Discards any incoming data.
 */
public class DiscardServer {
    private int port;
    public DiscardServer(int port) {
        this.port = port;
    }
    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap(); // (2)
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class) // (3)
             .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new DiscardServerHandler());
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)          // (5)
             .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
            // Bind and start to accept incoming connections.
            ChannelFuture f = b.bind(port).sync(); // (7)
            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws Exception {
        int port = 8080;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        }
        new DiscardServer(port).run();
    }
}
  • NioEventLoopGroup是处理I / O操作的多线程事件循环。Netty为不同类型的传输提供了各种EventLoopGroup实现。在此示例中,我们正在实现服务器端应用程序,因此将使用两个NioEventLoopGroup。第一个通常称为“老板”,接受传入的连接。第二个通常称为“工人”,一旦老板接受连接并将注册的连接注册给工人,便处理已接受连接的流量。使用多少个线程以及如何将它们映射到创建的通道取决于EventLoopGroup实现,甚至可以通过构造函数进行配置。
  • ServerBootstrap是设置服务器的帮助程序类。可以直接使用channel来设置服务器。但是比较繁琐,在大多数情况下无需这样做。
  • 指定使用NioServerSocketChannel类,该类用于实例化新的Channel来接受传入的连接。
  • 指定的处理程序将始终由新接受的Channel评估。ChannelInitializer是一个特殊的处理程序,旨在帮助用户配置新的Channel。您很可能希望通过添加一些处理程序(例如DiscardServerHandler)来实现新的Channel的ChannelPipeline,以实现您的网络应用程序。随着应用程序变得复杂,可能会向管道中添加更多处理程序,并最终将此匿名类提取到顶级类中。
  • 可以设置特定Channel实现的参数。编写一个TCP / IP服务器,可以设置套接字选项,例如tcpNoDelay和keepAlive。
  • option()用于接受输入连接的NioServerSocketChannel。childOption()用于父级ServerChannel接受的通道,在这种情况下为NioSocketChannel。
  • 剩下的就是绑定到端口并启动服务器。在这里,我们绑定到计算机中所有NIC(网络接口卡)的端口8080。可以根据需要多次调用bind()方法(使用不同的绑定地址)。


   今天先做一个简单的了解,后续在看更多细节,欢迎交流~~

相关文章
|
6月前
|
缓存 网络协议 算法
Netty的基础入门(上)
Netty的基础入门(上)
223 1
|
6月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
209 0
|
7天前
|
消息中间件 编解码 网络协议
Netty从入门到精通:高性能网络编程的进阶之路
【11月更文挑战第17天】Netty是一个基于Java NIO(Non-blocking I/O)的高性能、异步事件驱动的网络应用框架。使用Netty,开发者可以快速、高效地开发可扩展的网络服务器和客户端程序。本文将带您从Netty的背景、业务场景、功能点、解决问题的关键、底层原理实现,到编写一个详细的Java示例,全面了解Netty,帮助您从入门到精通。
25 0
|
6月前
|
存储 消息中间件 缓存
Netty的基础入门(下)
Netty的基础入门(下)
119 0
|
6月前
|
前端开发 网络协议 Java
Netty入门指南:从零开始的异步网络通信
Netty入门指南:从零开始的异步网络通信
179 0
|
6月前
|
设计模式 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
221 1
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(一)
|
6月前
|
消息中间件 缓存 Java
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(二)
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
244 1
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(二)
|
6月前
|
消息中间件 缓存 Java
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
171 0
|
6月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析(二)
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
119 1
|
6月前
|
缓存 Java 数据挖掘
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(一)
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
148 0
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty(一)