Netty入门介绍

Posted WSYW126

tags:

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

背景

最近在看如何实现一个简单的RPC服务。所使用的技术涉及到:Zookeeper、netty、spring。这篇文章不讲怎么实现RPC。因为涉及到了netty,所以我就去看了一下netty的一些资料。这里先大概讲一下netty,来个入门认识。

netty入门介绍

netty官网

Netty是NIO客户端服务器框架,能够快速轻松地开发诸如协议服务器和客户端之类的网络应用程序。 它大大简化了网络编程流程,如TCP和UDP套接字服务器。

“快速而简单”并不意味着由此产生的应用程序将受到可维护性或性能问题的困扰。 Netty已经通过实施许多协议(如FTP,SMTP,HTTP以及各种基于二进制和基于文本的传统协议)获得的经验仔细设计。 因此,Netty成功地找到了一种方法来实现轻松的开发,性能,稳定性和灵活性,而无需妥协。

特征

设计

  1. 用于各种传输类型的统一API - 阻塞和非阻塞套接字
  2. 基于灵活可扩展的事件模型,可以明确分离问题
  3. 高度可定制的线程模型 - 单线程,一个或多个线程池,如SEDA
  4. 真正的无连接数据报插座支持(自3.1版)

使用方便

  1. 详细的Javadoc,用户指南和示例
  2. 没有额外的依赖关系,JDK 5(Netty 3.x)或6(Netty 4.x)就足够了

    注意:某些组件(如HTTP / 2)可能有更多的要求。 有关详细信息,请参阅“需求”页面。

性能

  1. 更好的吞吐量,更低的延迟
  2. 资源消耗减少
  3. 最小化不必要的内存副本

安全

  1. 完成SSL / TLS和StartTLS支持

netty例子

官网站给的例子很充分,去clone下来看下就可以了。我看的是3.7的版本

放个栗子:

服务器通常应该响应请求。 我们学习如何通过实现ECHO协议向客户端写入响应消息,其中任何接收到的数据都将被发回。

public class EchoServerHandler extends SimpleChannelUpstreamHandler 

    private static final Logger logger = Logger.getLogger(
            EchoServerHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();

    public long getTransferredBytes() 
        return transferredBytes.get();
    

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
        e.getChannel().write(e.getMessage());
    

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) 
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.", e.getCause());
        e.getChannel().close();
    



public class EchoServer 

    private final int port;

    public EchoServer(int port) 
        this.port = port;
    

    public void run() 
        // Configure the server.
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioserverSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
            public ChannelPipeline getPipeline() throws Exception 
                return Channels.pipeline(new EchoServerHandler());
            
        );

        // Bind and start to accept incoming connections.
        bootstrap.bind(new InetSocketAddress(port));
    

    public static void main(String[] args) throws Exception 
        int port;
        if (args.length > 0) 
            port = Integer.parseInt(args[0]);
         else 
            port = 8080;
        
        new EchoServer(port).run();
    



public class EchoClientHandler extends SimpleChannelUpstreamHandler 

    private static final Logger logger = Logger.getLogger(
            EchoClientHandler.class.getName());

    private final ChannelBuffer firstMessage;
    private final AtomicLong transferredBytes = new AtomicLong();

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler(int firstMessageSize) 
        if (firstMessageSize <= 0) 
            throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
        
        firstMessage = ChannelBuffers.buffer(firstMessageSize);
        for (int i = 0; i < firstMessage.capacity(); i ++) 
            firstMessage.writeByte((byte) i);
        
    

    public long getTransferredBytes() 
        return transferredBytes.get();
    

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) 
        // Send the first message.  Server will not send anything here
        // because the firstMessage's capacity is 0.
        e.getChannel().write(firstMessage);
    

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
        e.getChannel().write(e.getMessage());
    

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) 
        // Close the connection when an exception is raised.
        logger.log( Level.WARNING,"Unexpected exception from downstream.",e.getCause());
        e.getChannel().close();
    


public class EchoClient 

    private final String host;
    private final int port;
    private final int firstMessageSize;

    public EchoClient(String host, int port, int firstMessageSize) 
        this.host = host;
        this.port = port;
        this.firstMessageSize = firstMessageSize;
    

    public void run() 
        // Configure the client.
        ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
            public ChannelPipeline getPipeline() throws Exception 
                return Channels.pipeline(
                        new EchoClientHandler(firstMessageSize));
            
        );

        // Start the connection attempt.
        ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));

        // Wait until the connection is closed or the connection attempt fails.
        future.getChannel().getCloseFuture().awaitUninterruptibly();

        // Shut down thread pools to exit.
        bootstrap.releaseExternalResources();
    

    public static void main(String[] args) throws Exception 
        // Print usage if no argument is specified.
        if (args.length < 2 || args.length > 3) 
            System.err.println("Usage: " + EchoClient.class.getSimpleName() +" <host> <port> [<first message size>]");
            return;
        

        // Parse options.
        final String host = args[0];
        final int port = Integer.parseInt(args[1]);
        final int firstMessageSize;
        if (args.length == 3) 
            firstMessageSize = Integer.parseInt(args[2]);
         else 
            firstMessageSize = 256;
        

        new EchoClient(host, port, firstMessageSize).run();
    

理解

netty的编程实现的方式是:服务器端开放出自己的端口,客户端去将请求发送到服务器端的该端口号。这个和一般的项目是一样的。不一样的是netty封装了很多东西,使得我们不必去理会底层的一些知识,可以直接来快捷的编程。

使用方式:

服务器端通过ServerBootstrap来配置服务,然后设置管道工厂,并加入处理方法EchoServerHandler,然后将服务绑定到指定的端口号和开始接受请求。

客户端通过ServerBootstrap来配置客户端的配置,然后设置管道工厂,并加入处理方法EchoClientHandler,然后将请求发送到指定的地址和端口号,开始接受。然后等待返回的结果(也可以不等待),最后关闭线程。

在这些操作中几乎是差不多的,只不过是需求不一样,配置不一样。

对数据流的处理的方法在Handler这个类中,我们可以在这个类里实现自己需要的东西。比如该例子就是继承SimpleChannelUpstreamHandler,然后在其中放入echo所需要的代码。


参考资料:
网上资料
备注:
转载请注明出处:http://blog.csdn.net/wsyw126/article/details/75212978
作者:WSYW126

以上是关于Netty入门介绍的主要内容,如果未能解决你的问题,请参考以下文章

netty入门及介绍

精通并发与Netty入门一:Netty理论知识介绍

七.Netty入门到超神系列-Netty介绍和线程模型

从入门到实战,Netty多线程篇案例集锦

Netty入门系列 --使用Netty进行编解码的操作

即时通讯开发之Netty入门长文:基本介绍环境搭建