深入Netty(二)-Netty基础编程

1,293 阅读2分钟

上一篇已经通过一个示例来了解了一下jdk的nio编程,这篇我们也通过一个简单的示例来学习一下netty的基础编程。

需求很简单,客户端发送一条信息给服务端,服务端接收信息并打印,然后回复给客户端,一次通信即结束。

首先编写一个服务端的处理handle

public class ServerExampleHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client connect");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client close");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg);
        ctx.channel().writeAndFlush("hello I am server");
    }
}

三个方法分别对应着连接打开,连接关闭,和消息接收三个事件。

服务端代码如下:

public class NettyServer {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup boss = new NioEventLoopGroup(1);
        EventLoopGroup worker = new NioEventLoopGroup(8);

        ServerBootstrap b = new ServerBootstrap();
        try {

            b.group(boss, worker)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<NioSocketChannel>() {
                 @Override
                 protected void initChannel(NioSocketChannel ch) throws Exception {
                     //这两个handle为netty自带的
                     ch.pipeline().addLast(new StringDecoder());
                     ch.pipeline().addLast(new StringEncoder());
                     //这是实现我们自定义逻辑的handle
                     ch.pipeline().addLast(new ServerExampleHandler());
                 }
             });
            b.bind(8080).channel().closeFuture().sync();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

}

其次编写客户端的处理handle

public class ClientExampleHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush("I am client");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg);
        ctx.close();
    }
}

客户端代码如下:

public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup(1);
        Bootstrap b = new Bootstrap();

        try {
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<NioSocketChannel>() {
                 @Override
                 protected void initChannel(NioSocketChannel ch) throws Exception {
                     //这两个handle为netty自带的
                     ch.pipeline().addLast(new StringDecoder());
                     ch.pipeline().addLast(new StringEncoder());
                     //这是实现我们自定义逻辑的handle
                     ch.pipeline().addLast(new ClientExampleHandler());
                 }
             });
            b.connect("127.0.0.1", 8080).channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }

}

这样一个服务端和客户端相互通信的功能就已经实现了。

其实在上述的netty编程中,我们自己写的逻辑主要就是两个handle,其他的代码都属于netty框架。可以和jdk的代码做个比较,netty的编程,明显可以让我们更专注于业务逻辑。

那么netty到底替我们做了那些事情呢?万变不离其宗,IO编程的两大步骤

  1. 接收连接
  2. 处理消息

netty也是一样。接下来我们就看看netty到底是怎么完成这两个步骤的。