netty学习(入门篇)

netty学习(入门篇)

netty诞生简介

2002年之前,那时候java还没有nio的概念,没有channel,没有缓冲区,io模式是同步阻塞的,想要编写高性能的服务器几乎是不可能的,那时候基本上服务器都是由c,c++编写的,直到jdk1.4java第一次支持了nio,这个类库为java通信模式带来了翻天覆地的变化,从那一年开始java慢慢在服务器开发占据了一席之地,但是nio编程也有很大的缺陷,代码复杂度很高,门槛很高,扩展性复用性都不是很好而且还有seletor空轮询bug,不过现在好像已经修复的差不多了。nio是同步非阻塞io,jdk1.7对nio进行了升级成aio异步非阻塞,主要是提供了基于文件的异步io操作和网络套接字的异步io操作。鉴于nio编程的复杂性,不稳定性,就有人帮我们造轮子了,netty是jboss提供一个高性能的异步的非阻塞的基于事件驱动的网络通讯框架,使用netty我们可以快速开发出稳定高效的服务器。
当然,所有这些io都是基于操作系统的io模型来实现的
select,poll,epoll模型在我之前的并发编程专栏里有专门的文章说明,之前花了半个月学习io模型对我帮助很大,虽然刚开始接触netty,但感觉一点都不难理解

netty服务器

public class EchoServer {
    private final int port;

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

    public static void main(String[] args) throws InterruptedException {
        new EchoServer(9999).start();
    }

    private void start() throws InterruptedException {
        // 入门案例使用Reactor单线程模型
        // 接收客户端的TCP连接;向通信对端发送消息请求或者应答消息;
        EventLoopGroup group = new NioEventLoopGroup();
        try {
        //服务器启动类,把所有组件串起来    
        ServerBootstrap server = new ServerBootstrap();
        server.group(group)
                .channel(NioServerSocketChannel.class)
                .localAddress(new InetSocketAddress(port))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    //Handler主要是做编解码和业务逻辑处理
                    //为什么要做编解码,因为数据在网络上都是字节传输的(也可以说二进制,只不过粒度小点而已)
                    //而我们接收数据期望收到的可不是字节,而是基本数据类型或者对象。所以要做编解码
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //这里是拦截链模式,解码器(入站)->编码器(出站)->业务逻辑处理
                        socketChannel.pipeline().addLast("decoder", new StringDecoder());
                        socketChannel.pipeline().addLast("encoder", new StringEncoder());
                        socketChannel.pipeline().addLast(new EchoServerHandler());
                    }
                });
        ChannelFuture future = server.bind().sync();

        System.out.println(EchoServer.class.getName() + " started and listen on " + future.channel().localAddress());
        future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }
}

@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter{
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Server received: " + msg);        //2
        ctx.write(msg);
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE);
        //冲刷所有待审消息到远程节点。关闭通道后,操作完成
    }

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

netty客户端

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 Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .remoteAddress(new InetSocketAddress(host, port))
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) 
                     throws Exception {
                     ch.pipeline().addLast("decoder", new StringDecoder());
                     ch.pipeline().addLast("encoder", new StringEncoder());
                     ch.pipeline().addLast(new EchoClientHandler());
                 }
             });

            ChannelFuture future = b.connect().sync();
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws Exception {
        new EchoClient("localhost", 9999).start();
    }
}
@ChannelHandler.Sharable
public class EchoClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        ctx.writeAndFlush("Netty rocks!\r\n");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Client received: " + msg);
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
        Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}
发布了127 篇原创文章 · 获赞 68 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/LiuRenyou/article/details/100986617