Netty笔记(一)第一个程序

    这两天学习netty,记录一下。

    netty 介绍不废话。

    官方网站:http://netty.io/

    使用netty高层次抽象的API,无需编写底层的NIO、或java7 的NIO.2 代码,并且完美兼容。

    使用netty高层次抽象的API,完美融合并发编程中的futrue跟callback模式,编写出优雅且易维护,高性能的应用。

    使用netty高层次抽象的API,可以实践传说中的SEDA,编写出号称支持高并发的应用。

    使用netty高层次抽象的API,您再也不用为编写多线程应用难度而烦恼。

    初初看,给我的感觉这样的,好好学习,天天向上。

    传统Server端处理不同连接客户端的办法:

    Netty笔记(一)第一个程序_第1张图片

    使用NIO之后:

Netty笔记(一)第一个程序_第2张图片

    实践Echo程序:

    创建Maven工程。pom.xml需要的依赖。

<dependencies>
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.0.0.Final</version>
        </dependency>
    </dependencies>

    EchoServer.java

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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 java.net.InetSocketAddress;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author XzF
 */
public class EchoServer
{

    private final int port;

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

    public void start() throws InterruptedException
    {

        EventLoopGroup group = new NioEventLoopGroup();
        try
        {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group( group )//
                    .channel( NioServerSocketChannel.class )//
                    .localAddress( new InetSocketAddress( port ) )//
                    .childHandler(
                            new ChannelInitializer<SocketChannel>()
                            {
                                @Override
                                protected void initChannel( SocketChannel ch ) throws Exception
                                {
                                    ch.pipeline().addLast( new EchoServerHandler() );
                                }
                            } //
                    );
            ChannelFuture f = bootstrap.bind().sync();
            System.out.println(
                    EchoServer.class.getName()
                    + " started and listen on " + f.channel().localAddress()
            );

            f.channel().closeFuture().sync();
        }
        finally
        {
            group.shutdownGracefully().sync();
        }
    }

    public static void main( String[] args )
    {
        int port = 9999;
        if ( args.length == 1 )
        {
            port = Integer.parseInt( args[0] );
        }
        System.out.println( "Usage: . + EchoServer.class.getSimpleName() +. <port> : " + port );
        try
        {
            new EchoServer( port ).start();
        }
        catch ( InterruptedException ex )
        {
            Logger.getLogger( EchoServer.class.getName() ).log( Level.SEVERE, null, ex );
        }
    }

}

    # 创建ServerBootstarp,用于Server端启动。

    # 创建EventLoopGroup ,绑定于ServerBootstarp。

    # 绑定使用NioServerSocketChannel

    # 绑定端口

    # 设置起动的ChannelInitialzer,在其管道对象中加入我们自定义的服务端处理的EchoHandler

    # ServerBootstartp进行调用原来绑定,并阻塞等其执行完成,返回其ChannelFuture对象

    # ChannelFuture.channel().closeFuture().sync() ,阻塞等待Server关闭。

    # 释放EventLoopGroup所用的资源。

    EchoServerHandler.java

@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter
{

    @Override
    public void channelRead( ChannelHandlerContext ctx, Object msg ) throws Exception
    {
      //  System.out.println( "Server received :" + msg );
        //  ctx.write( msg );
        ByteBuf in = (ByteBuf) msg;
        System.out.println( "Server received: " + ByteBufUtil
                .hexDump( in ) );
        ctx.write( in );
    }

    @Override
    public void channelReadComplete( ChannelHandlerContext ctx ) throws Exception
    {
        ctx.writeAndFlush( Unpooled.EMPTY_BUFFER ).addListener( ChannelFutureListener.CLOSE );
    }

    @Override
    public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
        ctx.close();
    }

}

     # channelRead ,当获取到客户端信息时执行。通过ctx写回给客户端。

     # 继承来自ChannelInboundHandlerAdapter,在执行完chanelRead方法后,释放相关NIO资源。

    

客户端

EchoClient.java

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.net.InetSocketAddress;

/**
 *
 * @author XzF
 */
public class EchoClient
{

    private final String host;
    private final int port;

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

    public void start() throws InterruptedException
    {
        EventLoopGroup group = new NioEventLoopGroup();
        try
        {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group( group )//
                    .channel( NioSocketChannel.class )//
                    .remoteAddress( new InetSocketAddress( host, port ) )//
                    .handler( new ChannelInitializer<SocketChannel>()
                            {
                                @Override
                                protected void initChannel( SocketChannel ch ) throws Exception
                                {
                                    ch.pipeline().addLast( new EchoClientHandler() );
                                }
                    } );
            ChannelFuture f = bootstrap.connect().sync();
            f.channel().closeFuture().sync();
        }
        finally
        {
            group.shutdownGracefully().sync();
        }
    }

    public static void main( String[] args )
    {
        String host = "127.0.0.1";
        int port = 9999;
        if ( args.length > 0 )
        {
            host = args[0];
            port = Integer.parseInt( args[1] );
        }

        System.out.println(
                "Usage: " + EchoClient.class.getSimpleName()
                + " <host> " + host + " <port> :" + port );

        try
        {
            new EchoClient( host, port ).start();
        }
        catch ( InterruptedException ex )
        {
            ex.printStackTrace();
        }

    }

}
#跟服务端大同小异,编写自定义EchoClientHandler

EchoClientHandler.java

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

/**
 *
 * @author XzF
 */
@Sharable
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf>
{

    @Override
    public void channelActive( ChannelHandlerContext ctx ) throws Exception
    {
        String msg = "Netty rocks!";
        System.out.println( "Clinent sended : " + msg );
        ctx.writeAndFlush( Unpooled.copiedBuffer( msg, CharsetUtil.UTF_8 ) );
    }

    @Override
    protected void channelRead0( ChannelHandlerContext ctx, ByteBuf in ) throws Exception
    {
      //  System.out.println( "Client received : "
      //                      + ByteBufUtil.hexDump( in.readBytes( in.readableBytes() ) ) );
        System.out.println("Client received: " + ByteBufUtil
                .hexDump(in));
    }

    @Override
    public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) throws Exception
    {
        cause.printStackTrace();
        ctx.close();
    }

}
 # channelActive ,在连接建立时调用,发送信息~

 # channelRead0 ,当读取到服务端数据时调用。

 # 继承SimpleChannelInboundHandler , 调用channelRead0 方法时不会及时清空资源,些类维护了NIO资源的释放,因不能保证一次调用channelRead0 方法已经将读取到的bytes全部带过来,但能维护顺序。

maven打包,编译后执行。

服务端:

客户端:

Netty笔记(一)第一个程序_第3张图片

你可能感兴趣的:(netty,笔记)