Netty4.x用户指导

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty4.x用户指导相关的知识,希望对你有一定的参考价值。

题记

最近对netty有了兴趣,现在官方推荐版本是netty4.*,但是纵观网络,大部分都是关于netty3.x的知识。

最好的学习,莫过于通过官方文档进行学习,系统,透彻,权威,缺点是英文。本文,算做自己学习netty的第一篇,总体思路与User guide for 4.x基本一致,本篇文章不是严格意义的翻译文章。开始了...

1.前言

1.1 问题

现 在,我们使用通用的应用程序和程序库,进行互相交流。例如,我们经常使用HTTP client库从web服务器上获取信息,通过web services调用远程接口。然而,通用的协议或实现,有时候不能很好的扩展伸缩。就像我们不能使用通用协议进行部分信息的交换,如:huge files,e-mail,实时信息。我们需要高度优化的协议实现,来完成一些特殊目的。比如,你想实现一款专门的HTTP服务器,以支持基于AJAX的聊天应用,流媒体,大文件传输。你需要设计和实现一个完整的新协议,不可避免需要处理遗留协议,在不影响性能和稳定的情况下,实现新协议速度能有多块?

1.2 解决方案

Netty 致力于提供异步,基于事件驱动的网络应用框架,是一款进行快速开发高性能,可伸缩的协议服务器和客户端工具。换句话说,Netty是一个快速和容易开发的NIO客户端,服务端网络框架,它简化和使用流式方式处理网络编程,如TCP,UDP。

"快速和容易“,并不代表netty存在可维护性和性能问题。它很完美的提供FTP,SMTP,HTTP,二进制和基于文本的协议支持。有的用户可能已经发现了拥有同样有点的其他网络应用框架。你可能想问:netty和他们的区别?这个问题不好回答,Netty被设计成提供最合适的API和实现,会让你的生活更简单。

2.开始

本节使用一些简单的例子让你快速的感知netty的核心结构。阅读本节之后,你可以熟练掌握netty,可以写一个client和server。

准备

JDK 1.6+

最新版本的netty:下载地址

maven依赖

<dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty-all</artifactId>
   <version>${netty.version}</version>
</dependency>


2.1写一个Discard服务

最简单的协议,不是‘hello world‘,而是DISCARD。这个协议抛弃接收的数据,没有响应。

协议实现,唯一需要做的一件事就是无视所有接收到的数据,让我们开始吧。

直接上Handler的实现,它处理来自netty的I/O事件。

package io.netty.examples.discard;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
/**
 * 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)
        /*
        //也可以这样
         try {        // Do something with msg
              } finally {
                      ReferenceCountUtil.release(msg);
            }        
        */
        
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}


1)DiscardServerHandler继承了ChannelInboundHandlerAdapter

实现了ChannelInboundHandler接口。ChannelInboundHandler提供了多个可重写的事件处理方法。现在,继承了ChannelInboundHandlerAdapter,而不用自己实现handler接口。

2)重写了channelRead(),这个方法在接收到新信息时被调用。信息类型是ByteBuf

3)实现Discard协议,ByteBuf是reference-counted对象,必须显示的调用release(),进行释放。需要记住handler的责任包括释放任意的reference-counted对象。

4)exceptionCaught(),当发生异常时调用,I/O异常或Handler处理异常。一般情况下,在这里可以记录异常日志,和返回错误码。

到了这里,完成了一半,接下来编写main(),启动Server

package io.netty.examples.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;
import io.netty.examples.discard.time.TimeServerHandler;

/**
 * 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 TimeServerHandler());
                 }
             })
             .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;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        } else {
            port = 8080;
        }
        new DiscardServer(port).run();
    }
}
  1. NioEventLoopGroup 是一个多线程的处理I/O操作Event Loop(这是异步机制特点) Netty 提供了多个 EventLoopGroup,支持多种传输方式。在这个例子中,我们使用了2个NioEventLoopGroup


    第一个,叫"boss",接收进入的连接,第二个经常叫“worker",一旦boss接收了连接并注册连接到这个worker,worker就会处理这个连接。多少个线程被使用?,EventLoopGroup拥有多少个Channel?都可以通过构造函数配置

  2. ServerBootstrap是建立server的帮助类。你可以使用Channel直接创建server,注意,这个创建过程非常的冗长,大部分情况,你不需要直接创建。

  3. 指定 NioServerSocketChannel类,当接收新接入连接时,被用在Channel的初始化。

  4. 这个handler,初始化Channel时调用。ChannelInitializer是一个专门用于配置新的Channel的Handler,一般为Channel配置ChannelPipeline。当业务复杂时,会添加更多的handler到pipeline.

  5. 你可以设置影响Channel实现的参数,比如keepAlive..

  6. option()  影响的是接收进入的连接 的NioServerSocketChannel ;childOption()影响的是来自父 ServerChannel分发的Channel, 在本例中是 NioServerSocketChannel

  7. 保证工作准备好了


通过telnet进行测试。

输入telnet 127.0.0.1 8080

技术分享

由于是Discard协议,一没响应,二服务端也没输出。通过测试,只能确认是服务正常启动了。

调整下Handler逻辑,修改channelRead()方法。

@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {
    ByteBuf in = (ByteBuf) msg;
        try {
           while (in.isReadable()) { // (1)
             System.out.print((char) in.readByte());
            System.out.flush();
             }
    } finally {
            ReferenceCountUtil.release(msg); // (2)
    }
}



待补充






本文出自 “简单” 博客,请务必保留此出处http://dba10g.blog.51cto.com/764602/1789639

以上是关于Netty4.x用户指导的主要内容,如果未能解决你的问题,请参考以下文章

Netty4.x实战专题案例文章列表

Netty4.xNetty TCP粘包/拆包问题的解决办法

netty4.x ByteBuf 基本机制及其骨架实现

Netty入门(Netty4.x使用指南)

聊天软件开发之Netty3.x VS Netty4.x的线程模型总结

用于流式服务器的 Netty 4.x.x WebSocket 握手