初识Netty

Netty是什么

  参考文献:极客时间傅健老师的《Netty源码剖析与实战》Talk is cheap.show me the code!

  官网(https://netty.io/)表明:“Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.”,翻译过来就是:Netty是一个异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。简单的拆分可以理解:

①本质:网络应用程序框架

②实现:异步、事件驱动

③特性:高性能、可维护、快速开发

④用途:开发服务器和客户端

   这是官网给的一张结构图:

不难看出Nettty一共有三个部分,最底层是核心层,从下往上看,最下面是"零拷贝Buffer",往上一格是"通信层API",再上一格则是"拓展的事件模型",左上是传输层服务,包括Http的Tunnel,TCP的Socket,UDP的Datagram等等,右上则是Netty支持的各种各样的协议,比如我们常说的HTTP协议,WebSocket协议,Google的ProtoBuf协议等等。

第一个HelloWorld

  用InterlliJ IDEA建立一个Maven工程,在pom.xml配置文件加入Netty的依赖

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

编写服务器端MyService.java

package com.lql.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
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.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description:     第一个Netty程序     服务器
 */
public class MyServer {


    public static void main(String[] args) throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    p.addLast(new LoggingHandler(LogLevel.INFO));
                    p.addLast(new MyServerHandler());
                }
            });

            ChannelFuture f = sb.bind(8090).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}

编写MyServerHandler.java

package com.lql.netty;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description:
 */
@Sharable
public class MyServerHandler extends ChannelInboundHandlerAdapter {


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ctx.write(msg);
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        cause.printStackTrace();
        ctx.close();
    }
}

再来编写客户端MyClient.java

package com.lql.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description: 第一个Netty程序     客户端
 */
public class MyClient {

    public static void main(String[] args) throws Exception {
        //客户端只需要一个事件循环组
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new LoggingHandler(LogLevel.INFO));
                            p.addLast(new MyClientHandle());
                        }
                    });

            //开始客户端
            ChannelFuture f = b.connect("127.0.0.1",8090).sync();
            //等待连接关闭
            f.channel().closeFuture().sync();

        } finally {
            //优雅关闭
            group.shutdownGracefully();
        }

    }
}

同样,创建MyClientHandle.java

package com.lql.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.concurrent.TimeUnit;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description:
 */
public class MyClientHandle extends ChannelInboundHandlerAdapter{

    private final ByteBuf firstMessage;

    public MyClientHandle() {
        firstMessage = Unpooled.wrappedBuffer("I am echo message".getBytes());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        ctx.flush();
    }

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

先启动服务器,后启动客户端,结果是可行的!

Netty也可以和Spring mvc一样。如下所示:

建立HttpServer.java

package com.lql.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description:
 * Created with IntelliJ IDEA
 */
public class HttpServer {


    public static void main(String[] args) throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer() {
                        protected void initChannel(Channel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();
                            p.addLast(new HttpServerCodec());
                            p.addLast(new HttpServerExpectContinueHandler());
                            p.addLast(new HttpServerHandler());
                        }
                    });

            ChannelFuture channelFuture = b.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();

        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

再建立HttpServerHandler.java

package com.lql.netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;

/**
 * @author: lql
 * @date: 2019.10.14
 * Description:
 * Created with IntelliJ IDEA
 */
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {


    private static final byte[] CONTENT = "helloworld".getBytes();

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
        if (msg instanceof HttpRequest) {
            HttpRequest req = (HttpRequest) msg;

            FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), HttpResponseStatus.OK,
                    Unpooled.wrappedBuffer(CONTENT));
            response.headers()
                    .set(HttpHeaderNames.CONTENT_TYPE, "text/plain")
                    .setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
            ctx.write(response);
        }
    }

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

启动HttpServer:在网址输“http://localhost:8899/”,显示如下:

至此,Netty的HelloWorld已经写完了!

猜你喜欢

转载自www.cnblogs.com/-qilin/p/11671763.html