Netty的httpserver执行流程分析

Netty的httpserver执行流程分析

在上一篇文章,我们用Netty进行了一个建议的HttpServer的编写,在本文,我们对该server的执行流程做简要的分析。

回调函数介绍

我们在上一节编写的TestHttpServerHandler类是继承SimpleChannelInboundHandler类,该类是专门对客户端发送请求进行处理的类。通过观察源码,我们发现该类又继承了ChannelInboundHandlerAdapter类。
SimpleChannelInboundHandler源码

ChannelInboundHandlerAdapter类中有很多回调函数,例如handlerAdded,channelActive,channelInactive,channelRegistered,channelUnregistered等函数。这些函数分别是在handler被加入时,channel被注册和取消注册时以及channel被激活时由Netty框架进行调用。
我们在TestServerInitializer类中覆盖这五个方法,如下所示。

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel active");
        super.channelActive(ctx);
    }
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel inactive");
        super.channelInactive(ctx);
    }
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel registered");
        super.channelRegistered(ctx);
    }
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel unregistered");
        super.channelUnregistered(ctx);
    }
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("handler added");
        super.handlerAdded(ctx);
    }

然后我们用curl命令对服务器进行请求看看服务器终端中会出现什么结果:

curl

服务器返回结果如下所示:

Netty的httpserver执行流程分析_第1张图片

可以看到server的执行流程是按照如下五步进行的。

  1. handler added
  2. channel registered
  3. channel active
  4. channel inactive
  5. channel unregistered

但是如果我们用浏览器(Chrome)对服务器进行请求时,却发现命令行返回结果如下图所示。

Netty的httpserver执行流程分析_第2张图片
在该图中,每一步都执行了两次,并且没有channel inactive和channel unregistered输出,这是为什么呢?

打开google开发者工具,点击Network,我们可以看到,浏览器不仅请求了localhost根目录,还请求了favicon.ico文件,所以一共执行了两个请求,所以每一步都执行了两次。

(注意不同浏览器请求不同,比如说Firefox中就不会请求localhost两次)

Netty的httpserver执行流程分析_第3张图片

当我们关闭Chrome标签时,终端输出了如下信息。

Netty的httpserver执行流程分析_第4张图片
所以我们知道在浏览器打开localhost的时候请求一直都保持连接,所以不会输出channel inactive和channel unregistered。

而因为curl是网络命令工具,在curl请求完之后,请求就关闭掉了,所以会直接输出channel inactive和channel unregistered信息。

如果是spring MVC框架,在处理完请求返回给用户之后,Tomcat会保证响应的连接会自动关闭掉。但是Netty需要自己做,需要自己写代码令服务器端主动关闭连接。

在channelRead0函数末尾加上*ctx.channel().close();*代码之后,浏览器在请求过后,服务器会自动关闭连接。
最终代码如下图所示。

package com.first.netty.example;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.net.URI;
import java.nio.ByteBuffer;

public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
     
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
     
        if (msg instanceof HttpRequest) {
     
            ByteBuf content = Unpooled.copiedBuffer("Hello, World", CharsetUtil.UTF_8);
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
            ctx.writeAndFlush(response);
            ctx.channel().close();
        }

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel active");
        super.channelActive(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel registered");
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel unregistered");
        super.channelUnregistered(ctx);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("handler added");
        super.handlerAdded(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
     
        System.out.println("channel inactive");
        super.channelInactive(ctx);
    }
}

你可能感兴趣的:(Netty,http执行流程,channel流程,netty,http,server)