Netty之——搭建HttpServer

认识Http请求

在动手写Netty框架之前,我们先要了解http请求的组成,如下图:

Netty之——搭建HttpServer

  • HTTP Request 第一部分是包含的头信息
  • HttpContent 里面包含的是数据,可以后续有多个 HttpContent 部分
  • LastHttpContent 标记是 HTTP request 的结束,同时可能包含头的尾部信息
  • 完整的 HTTP request,由1,2,3组成

Netty之——搭建HttpServer

  • HTTP response 第一部分是包含的头信息
  • HttpContent 里面包含的是数据,可以后续有多个 HttpContent 部分
  • LastHttpContent 标记是 HTTP response 的结束,同时可能包含头的尾部信息
  • 完整的 HTTP response,由1,2,3组成

从request的介绍我们可以看出来,一次http请求并不是通过一次对话完成的,他中间可能有很次的连接。通过上一章我们队netty的了解,每一次对话都会建立一个channel,并且一个ChannelInboundHandler一般是不会同时去处理多个Channel的
如何在一个Channel里面处理一次完整的Http请求?这就要用到我们上图提到的FullHttpRequest,我们只需要在使用netty处理channel的时候,只处理消息是FullHttpRequest的Channel,这样我们就能在一个ChannelHandler中处理一个完整的Http请求了。

开始动手

搭建一个Netty服务器,我们只需要两个类——一个是启动类,负责启动(BootStrap)和main方法,一个是ChannelHandler,负责具体的业务逻辑,我们先从启动类说起。

package com.dz.netty.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

/**
 * Created by RoyDeng on 17/7/20.
 */
public class HttpServer {

    private final int port;

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

    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.err.println(
                    "Usage: " + HttpServer.class.getSimpleName() +
                            " <port>");
            return;
        }
        int port = Integer.parseInt(args[0]);
        new HttpServer(port).start();
    }

    public void start() throws Exception {
        ServerBootstrap b = new ServerBootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        b.group(group)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch)
                            throws Exception {
                        System.out.println("initChannel ch:" + ch);
                        ch.pipeline()
                                .addLast("decoder", new HttpRequestDecoder())   // 1
                                .addLast("encoder", new HttpResponseEncoder())  // 2
                                .addLast("aggregator", new HttpObjectAggregator(512 * 1024))    // 3
                                .addLast("handler", new HttpHandler());        // 4
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 128) // determining the number of connections queued
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);

        b.bind(port).sync();
    }
}

这个类同上一章中出现的Netty简易封装服务器代码类似,不一样的是这里使用了多个ChannelHandler,在这里一一介绍:

  1. HttpRequestDecoder,用于解码request
  2. HttpResponseEncoder,用于编码response
  3. aggregator,消息聚合器(重要)。为什么能有FullHttpRequest这个东西,就是因为有他,HttpObjectAggregator,如果没有他,就不会有那个消息是FullHttpRequest的那段Channel,同样也不会有FullHttpResponse。
    如果我们将z'h
    HttpObjectAggregator(512 * 1024)的参数含义是消息合并的数据大小,如此代表聚合的消息内容长度不超过512kb。
  4. 添加我们自己的处理接口

完成启动类之后,接下来就是我们的业务处理类HttpHandler了,先上代码:

 

 

 



 

 

 

 

 

 

 

 

 

 

转载:https://www.jianshu.com/p/ed0177a9b2e3

 

 

上一篇:Linux-虚拟机的安装


下一篇:WebApi-控制器路由