使用Netty实现HttpServer

package netty;

import static io.netty.handler.codec.http.HttpHeaderNames.CONNECTION;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.KEEP_ALIVE;

import com.alibaba.fastjson.JSON;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import lombok.Cleanup;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

/**
 * Test
 *
 * @author xfyou
 */
public class Test {

  @SneakyThrows
  public static void main(String[] args) {
    HttpServer server = new HttpServer(8080);
    server.start();
  }

  @RequiredArgsConstructor
  private static class HttpServer {

    private final Integer port;

    @SneakyThrows
    public void start() {
      EventLoopGroup bossGroup = new NioEventLoopGroup(1);
      EventLoopGroup workerGroup = new NioEventLoopGroup(20);
      try {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
            .option(ChannelOption.SO_BACKLOG, 128)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ChannelInitializerImpl());
        ChannelFuture future = serverBootstrap.bind(port).sync();
        System.out.println("Server started...");
        future.channel().closeFuture().sync();
      } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
      }
    }

  }

  private static final class ChannelInitializerImpl extends ChannelInitializer<Channel> {

    private final SslContext sslContext;

    @SneakyThrows
    public ChannelInitializerImpl() {
      sslContext = createSslContext();
    }

    @SneakyThrows
    private SslContext createSslContext() {
      String keyStoreFilePath = "/root/.ssl/test.pkcs12";
      String keyStorePassword = "passwd";
      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      @Cleanup InputStream inputStream = new FileInputStream(keyStoreFilePath);
      keyStore.load(inputStream, keyStorePassword.toCharArray());
      KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
      keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
      return SslContextBuilder.forServer(keyManagerFactory).build();
    }

    @Override
    protected void initChannel(Channel ch) {
      ChannelPipeline cp = ch.pipeline();
      // support SSL/TLS
      cp.addLast(new SslHandler(sslContext.newEngine(ch.alloc())));
      // decode and encode
      cp.addLast(new HttpServerCodec());
      // handle message-body of POST
      cp.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
      cp.addLast(new HttpServerExpectContinueHandler());
      cp.addLast(new SimpleChannelInboundHandler<FullHttpRequest>() {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
          System.out.println(msg.content().toString(StandardCharsets.UTF_8));
          System.out.println(ch);
          String res = "I am OK";
          FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(JSON.toJSONString(res).getBytes(StandardCharsets.UTF_8)));
          response.headers().set(CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
          response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
          if (HttpUtil.isKeepAlive(msg)) {
            response.headers().set(CONNECTION, KEEP_ALIVE);
            ctx.write(response);
          } else {
            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
          }
          ctx.flush();
        }
      });
    }
  }

}

原文地址:https://www.cnblogs.com/frankyou/p/12144087.html

时间: 2024-08-08 16:15:25

使用Netty实现HttpServer的相关文章

(中级篇 NettyNIO编解码开发)第十章-Http协议开发应用(基于Netty的HttpServer和HttpClient的简单实现)

1.HttpServer 1 package nettyHttpTest; 2 3 4 5 import io.netty.bootstrap.ServerBootstrap; 6 import io.netty.channel.ChannelFuture; 7 import io.netty.channel.ChannelInitializer; 8 import io.netty.channel.ChannelOption; 9 import io.netty.channel.EventLo

netty httpserver

netty也可以作为一个小巧的http服务器使用. 1 package com.ming.netty.http.httpserver; 2 3 import java.net.InetSocketAddress; 4 5 import io.netty.bootstrap.ServerBootstrap; 6 import io.netty.channel.ChannelFuture; 7 import io.netty.channel.ChannelInitializer; 8 import

HttpServer性能比较

在自己的本子上随便测了下几款HttpServer,环境信息就不贴出来了,主要是比对下差距. 测试内容是输出 text/plain 的 hello, world. 先说结论:Netty > JDK HttpServer > Jersey-Netty > Jersey-HttpServer > SpringBoot. 但需要注意下,第一名的Netty吞吐是第二名的HttpServer的2.7倍,而且errors表现也很优秀. Jersey 的 overhead 也摆在那儿,吞吐瞬间掉到

netty高级篇(3)-HTTP协议开发

一.HTTP协议简介 应用层协议http,发展至今已经是http2.0了,拥有以下特点: (1) CS模式的协议 (2) 简单 - 只需要服务URL,携带必要的请求参数或者消息体 (3) 灵活 - 任意类型,传输内容类型由HTTP消息头中的Content-Type加以标记 (4) 无状态 - 必须借助额外手段,比如session或者cookie来保持状态 1.1 HTTP请求消息(HttpRequest) 客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line

Netty In Action中国版 - 第二章:第一Netty程序

本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本章将简介Netty的核心概念,这个狠心概念就是学习Netty是怎样拦截和处理异常.对于刚開始学习netty的读者.利用netty的异常拦截机制来调试程序问题非常有帮助.本章还会介绍其它一些核心概念.如server和client的启动以及分离通道的处理程序.本章学习一些基础以便后面章节的深入学习. 本

Mina、Netty、Twisted一起学(五):整合protobuf

protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化.反序列化),一般应用于网络传输,可支持多种编程语言. protobuf怎样使用这里不再介绍,本文主要介绍在MINA.Netty.Twisted中怎样使用protobuf,不了解protobuf的同学能够去參考我的还有一篇博文. 在前面的一篇博文中.有介绍到一种用一个固定为4字节的前缀Header来指定Body的字节数的一种消息切割方式.在这里相同要使用到. 仅仅是当中Body的内容不再是字

Mina、Netty、Twisted一起学(十):线程模型

要想开发一个高性能的TCPserver,熟悉所使用框架的线程模型非常重要.MINA.Netty.Twisted本身都是高性能的网络框架,假设再搭配上高效率的代码.才干实现一个高大上的server. 可是假设不了解它们的线程模型.就非常难写出高性能的代码.框架本身效率再高.程序写的太差,那么server总体的性能也不会太高.就像一个电脑,CPU再好.内存小硬盘慢散热差,总体的性能也不会太高. 玩过Android开发的同学会知道,在Android应用中有一个非常重要线程:UI线程(即主线程). UI

【游戏开发】Netty TCP粘包/拆包问题的解决办法(二)

上一篇:[Netty4.X]Unity客户端与Netty服务器的网络通信(一) 一.什么是TCP粘包/拆包 如图所示,假如客户端分别发送两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是不确定的,故可能存在以下4中情况: 第一种情况:Server端分别读取到D1和D2,没有产生粘包和拆包的情况. 第二种情况:Server端一次接收到两个数据包,D1和D2粘合在一起,被称为TCP粘包. 第三种情况:Server端分2次读取到2个数据包,第一次读取到D1包和D2包的部分内容D2_1,第二次

netty与websocket通信demo

netty v3.9.4 websocket建立前,客户端需要与服务器进行握手 确认websocket连接,也就是说在处理websocket请求前,必需要处理一些http请求. websocket到现在为止,已经有多个版本,netty有相应的对应类,这部分处理一般不需要人工干预. 如果运行正常的话,会在页面的文本框中显示1-20记数. 可以通过firefox或chrome的开发人员工具,显看浏览器与服务器的交互. 主要是HttpServerChannelHandler2,加了些注释和少量debu