Netty入门

傷城~ 2022-03-16 07:22 374阅读 0赞

Netty是一个异步的事件驱动网络框架,使用Netty可以研发高性能的私有协议,将业务逻辑和网络进行解耦,通过Netty我们可以实现一些常用的协议,如HTTP。

基本概念

Channel

Channel是NIO的基础,它代表一个连接,通过这个链接可以进行IO操作,例如读和写。

Future

在Netty的Channel中的每一个IO操作都是非阻塞的。 这就意味着每一个操作都是立刻返回结果的。在Java标准库中有Future接口,但是我们使用Future的时候只能询问这个操作是否执行完成,或者阻塞当前的线程直到结果完成,这不是Netty想要的。

Netty实现了自己的ChannelFuture接口,我们可以传递一个回调到ChannelFuture,当操作完成的时候才会执行回调。

Events 和 Handlers

Netty使用的是事件驱动的应用设计,因此Handler处理的数据流,在管道中是链式的事件。事件和Handler可以被 输入 和 输出的数据流进行关联。

输入(Inbound)事件可以如下:

  • Channel激活和灭活
  • 读操作事件
  • 异常事件
  • 用户事件

输出(Outbound)事件比较简单,一般是打开和关闭连接,写入和刷新数据。

Encoder 和 Decoder

因为我们要处理网络协议,需要操作数据的序列化和反序列化。

代码

来个实际的案例:

  1. 新建项目,添加maven依赖


    4.1.6.Final
  1. <dependencies>
  2. <dependency>
  3. <groupId>io.netty</groupId>
  4. <artifactId>netty-all</artifactId>
  5. <version>${netty-all.version}</version>
  6. </dependency>
  7. </dependencies>
  8. 复制代码
  1. 创建数据的pojo

    public class RequestData {

    1. private int intValue;
    2. private String stringValue;
    3. // getter 和 setter
    4. // toString方法

    }

    public class ResponseData {

    1. private int intValue;
    2. // getter 和 setter
    3. // toString方法

    }

    复制代码

  2. 创建Encoder和Decoder

    public class RequestDataEncoder extends MessageToByteEncoder {

    1. private final Charset charset = Charset.forName("UTF-8");
    2. @Override
    3. protected void encode(ChannelHandlerContext channelHandlerContext, RequestData msg, ByteBuf out) throws Exception {
    4. out.writeInt(msg.getIntValue());
    5. out.writeInt(msg.getStringValue().length());
    6. out.writeCharSequence(msg.getStringValue(), charset);
    7. }

    }

    public class ResponseDataDecoder extends ReplayingDecoder {

    1. @Override
    2. protected void decode(ChannelHandlerContext ctx,
    3. ByteBuf in, List<Object> out) throws Exception {
    4. ResponseData data = new ResponseData();
    5. data.setIntValue(in.readInt());
    6. out.add(data);
    7. }

    }

  1. public class RequestDecoder extends ReplayingDecoder<RequestData> {
  2. private final Charset charset = Charset.forName("UTF-8");
  3. @Override
  4. protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
  5. RequestData data = new RequestData();
  6. data.setIntValue(in.readInt());
  7. int strLen = in.readInt();
  8. data.setStringValue(
  9. in.readCharSequence(strLen, charset).toString());
  10. out.add(data);
  11. }
  12. }
  13. public class ResponseDataEncoder extends MessageToByteEncoder<ResponseData> {
  14. @Override
  15. protected void encode(ChannelHandlerContext channelHandlerContext, ResponseData msg, ByteBuf out) throws Exception {
  16. out.writeInt(msg.getIntValue());
  17. }
  18. }
  19. 复制代码
  1. 创建请求的处理器

    public class ProcessingHandler extends ChannelInboundHandlerAdapter {

    1. @Override
    2. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    3. RequestData requestData = (RequestData) msg;
    4. ResponseData responseData = new ResponseData();
    5. responseData.setIntValue(requestData.getIntValue() * 2);
    6. ChannelFuture future = ctx.writeAndFlush(responseData);
    7. future.addListener(ChannelFutureListener.CLOSE);
    8. System.out.println(requestData);
    9. }

    }

  1. public class ClientHandler extends ChannelInboundHandlerAdapter {
  2. @Override
  3. public void channelActive(ChannelHandlerContext ctx)
  4. throws Exception {
  5. RequestData msg = new RequestData();
  6. msg.setIntValue(123);
  7. msg.setStringValue(
  8. "正常工作");
  9. ChannelFuture future = ctx.writeAndFlush(msg);
  10. }
  11. @Override
  12. public void channelRead(ChannelHandlerContext ctx, Object msg)
  13. throws Exception {
  14. System.out.println((ResponseData)msg);
  15. ctx.close();
  16. }
  17. }
  18. 复制代码
  1. 创建服务端应用

    public class NettyServer {

    1. private int port;
  1. public NettyServer(int port) {
  2. this.port = port;
  3. }
  4. public static void main(String[] args) throws Exception {
  5. int port = args.length > 0
  6. ? Integer.parseInt(args[0]) : 9003;
  7. new NettyServer(port).run();
  8. }
  9. public void run() throws Exception {
  10. EventLoopGroup bossGroup = new NioEventLoopGroup();
  11. EventLoopGroup workerGroup = new NioEventLoopGroup();
  12. try {
  13. ServerBootstrap b = new ServerBootstrap();
  14. b.group(bossGroup, workerGroup)
  15. .channel(NioServerSocketChannel.class)
  16. .childHandler(new ChannelInitializer<SocketChannel>() {
  17. @Override
  18. public void initChannel(SocketChannel ch)
  19. throws Exception {
  20. ch.pipeline().addLast(new RequestDecoder(),
  21. new ResponseDataEncoder(),
  22. new ProcessingHandler());
  23. }
  24. }).option(ChannelOption.SO_BACKLOG, 128)
  25. .childOption(ChannelOption.SO_KEEPALIVE, true);
  26. ChannelFuture f = b.bind(port).sync();
  27. f.channel().closeFuture().sync();
  28. } finally {
  29. workerGroup.shutdownGracefully();
  30. bossGroup.shutdownGracefully();
  31. }
  32. }
  33. }
  34. 复制代码
  1. 创建客户端应用

    public class NettyClient {

    1. public static void main(String[] args) throws Exception {
    2. String host = "127.0.0.1";
    3. int port = 9003;
    4. EventLoopGroup workerGroup = new NioEventLoopGroup();
    5. try {
    6. Bootstrap b = new Bootstrap();
    7. b.group(workerGroup)
    8. .channel(NioSocketChannel.class)
    9. .option(ChannelOption.SO_KEEPALIVE, true)
    10. .handler(new ChannelInitializer<SocketChannel>() {
    11. @Override
    12. public void initChannel(SocketChannel ch)
    13. throws Exception {
    14. ch.pipeline().addLast(new RequestDataEncoder(),
    15. new ResponseDataDecoder(), new ClientHandler());
    16. }
    17. });
    18. ChannelFuture f = b.connect(host, port).sync();
    19. f.channel().closeFuture().sync();
    20. } finally {
    21. workerGroup.shutdownGracefully();
    22. }
    23. }

    }
    复制代码

  2. 运行服务端和客户端

可见正常工作

最后

这里我们只是对Netty进行简单的介绍,介绍了它一些基本的概念,然后演示了一个例子。后续我们会对Netty进行更深入的研究

参考

  • Introduction to Netty
  • NIO教程

发表评论

表情:
评论列表 (有 0 条评论,374人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Netty入门

    概述 Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。 Netty底层用的是NIO,用netty为什么不直接用NIO?之

    相关 Netty入门

    Netty是一个异步的事件驱动网络框架,使用Netty可以研发高性能的私有协议,将业务逻辑和网络进行解耦,通过Netty我们可以实现一些常用的协议,如HTTP。 基本概念

    相关 Netty入门

    第二部分 Netty入门 netty可以运用在那些领域? 1分布式进程通信 例如: hadoop、dubbo、akka等具有分布式功能的框架,底层RPC通信都是基