<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Netty 實現(xiàn)簡單的HTTP服務器

          共 20701字,需瀏覽 42分鐘

           ·

          2021-04-12 16:45

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質文章,第一時間送達

          1 概述

          HTTP 是基于請求/響應模式的:客戶端向服務器發(fā)送一個 HTTP 請求,然后服務器將會返回一個 HTTP 響應。Netty 提供了多種編碼器和解碼器以簡化對這個協(xié)議的使用。一個HTTP 請求/響應可能由多個數(shù)據(jù)部分組成,F(xiàn)ullHttpRequest 和FullHttpResponse 消息是特殊的子類型,分別代表了完整的請求和響應。所有類型的 HTTP 消息(FullHttpRequest、LastHttpContent 等等)都實現(xiàn)了 HttpObject 接口。

          (1) HttpRequestEncoder 將 HttpRequest、HttpContent 和 LastHttpContent 消息編碼為字節(jié)。
          (2) HttpResponseEncoder 將 HttpResponse、HttpContent 和 LastHttpContent 消息編碼為字節(jié)。
          (3) HttpRequestDecoder 將字節(jié)解碼為 HttpRequest、HttpContent 和 LastHttpContent 消息。
          (4) HttpResponseDecoder 將字節(jié)解碼為 HttpResponse、HttpContent 和 LastHttpContent 消息。
          (5) HttpClientCodec 和 HttpServerCodec 則將請求和響應做了一個組合。

          1.1 聚合 HTTP 消息

          由于 HTTP 的請求和響應可能由許多部分組成,因此你需要聚合它們以形成完整的消息。

          為了消除這項繁瑣的任務,Netty 提供了一個聚合器 HttpObjectAggregator,它可以將多個消

          息部分合并為 FullHttpRequest 或者 FullHttpResponse 消息。通過這樣的方式,你將總是看

          到完整的消息內容。


          1.2 HTTP 壓縮

          當使用 HTTP 時,建議開啟壓縮功能以盡可能多地減小傳輸數(shù)據(jù)的大小。雖然壓縮會帶

          來一些 CPU 時鐘周期上的開銷,但是通常來說它都是一個好主意,特別是對于文本數(shù)據(jù)來

          說。Netty 為壓縮和解壓縮提供了 ChannelHandler 實現(xiàn),它們同時支持 gzip 和 deflate 編碼。


          2 代碼實現(xiàn)

          2.1 pom

          <dependencies>
                  <dependency>
                      <groupId>io.netty</groupId>
                      <artifactId>netty-all</artifactId>
                      <version>4.1.28.Final</version>
                  </dependency>
                  <dependency>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>4.11</version>
                  </dependency>
                  <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <version>1.18.20</version>
                      <scope>provided</scope>
                  </dependency>
                  <!--工具-->
                  <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
                  <dependency>
                      <groupId>org.apache.commons</groupId>
                      <artifactId>commons-lang3</artifactId>
                      <version>3.12.0</version>
                  </dependency>
                  <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
                  <dependency>
                      <groupId>org.apache.commons</groupId>
                      <artifactId>commons-collections4</artifactId>
                      <version>4.4</version>
                  </dependency>
                  <!--日志-->
                  <dependency>
                      <groupId>org.slf4j</groupId>
                      <artifactId>slf4j-api</artifactId>
                      <version>1.7.21</version>
                  </dependency>
                  <dependency>
                      <groupId>commons-logging</groupId>
                      <artifactId>commons-logging</artifactId>
                      <version>1.2</version>
                  </dependency>
                  <dependency>
                      <groupId>org.apache.logging.log4j</groupId>
                      <artifactId>log4j-api</artifactId>
                      <version>2.6.2</version>
                  </dependency>
                  <dependency>
                      <groupId>log4j</groupId>
                      <artifactId>log4j</artifactId>
                      <version>1.2.17</version>
                      <optional>true</optional>
                  </dependency>
                  <dependency>
                      <groupId>org.slf4j</groupId>
                      <artifactId>slf4j-simple</artifactId>
                      <version>1.7.25</version>
                  </dependency>
              </dependencies>



              <build>
                  <plugins>
                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-compiler-plugin</artifactId>
                          <configuration>
                              <source>8</source>
                              <target>8</target>
                          </configuration>
                      </plugin>
                  </plugins>
              </build>

          2.2 HttpConsts

          public class HttpConsts {

              private HttpConsts() {

              }

              public static final Integer PORT = 8888;

              public static final String HOST = "127.0.0.1";


          }


          2.3 服務端

          2.3.1 HttpServer

          @Slf4j
          public class HttpServer {

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

                  HttpServer httpServer = new HttpServer();
                  httpServer.start();
              }


              public void start() throws InterruptedException {


                  EventLoopGroup boss = new NioEventLoopGroup(1);
                  EventLoopGroup worker = new NioEventLoopGroup();

                  try {
                      ServerBootstrap serverBootstrap = new ServerBootstrap();
                      serverBootstrap.group(boss, worker)
                              .channel(NioServerSocketChannel.class)
                              .childHandler(new HttpServerHandlerInitial());
                      ChannelFuture channelFuture = serverBootstrap.bind(HttpConsts.PORT).sync();
                      log.info("服務器已開啟......");
                      channelFuture.channel().closeFuture().sync();
                  } finally {
                      boss.shutdownGracefully();
                      worker.shutdownGracefully();
                  }


              }


          }

          2.3.2 HttpServerBusinessHandler

          @Slf4j
          public class HttpServerBusinessHandler extends ChannelInboundHandlerAdapter {


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

                  //通過編解碼器把byteBuf解析成FullHttpRequest
                  if (msg instanceof FullHttpRequest) {

                      //獲取httpRequest
                      FullHttpRequest httpRequest = (FullHttpRequest) msg;

                      try {
                          //獲取請求路徑、請求體、請求方法
                          String uri = httpRequest.uri();
                          String content = httpRequest.content().toString(CharsetUtil.UTF_8);
                          HttpMethod method = httpRequest.method();
                          log.info("服務器接收到請求:");
                          log.info("請求uri:{},請求content:{},請求method:{}", uri, content, method);

                          //響應
                          String responseMsg = "Hello World";
                          FullHttpResponse response = new DefaultFullHttpResponse(
                                  HttpVersion.HTTP_1_1,HttpResponseStatus.OK,
                                  Unpooled.copiedBuffer(responseMsg,CharsetUtil.UTF_8)
                          );
                          response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain;charset=UTF-8");
                          ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                      } finally {
                          httpRequest.release();
                      }

                  }
              }
          }

          2.3.3 HttpServerHandlerInitial

          public class HttpServerHandlerInitial extends ChannelInitializer<SocketChannel> {


              @Override
              protected void initChannel(SocketChannel ch) throws Exception {

                  ChannelPipeline pipeline = ch.pipeline();

                  //http請求編解碼器,請求解碼,響應編碼
                  pipeline.addLast("serverCodec", new HttpServerCodec());
                  //http請求報文聚合為完整報文,最大請求報文為10M
                  pipeline.addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024));
                  //響應報文壓縮
                  pipeline.addLast("compress", new HttpContentCompressor());
                  //業(yè)務處理handler
                  pipeline.addLast("serverBusinessHandler", new HttpServerBusinessHandler());

              }
          }


          2.4 客戶端

          2.4.1 HttpClient

          public class HttpClient {


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

                  HttpClient httpClien = new HttpClient();
                  httpClien.start();

              }

              public void start() throws InterruptedException {
                  EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
                  try {
                      Bootstrap bootstrap = new Bootstrap();
                      bootstrap.group(eventLoopGroup)
                              .channel(NioSocketChannel.class)
                              .handler(new HttpClientHandlerInitial());

                      ChannelFuture f = bootstrap.connect(HttpConsts.HOST, HttpConsts.PORT).sync();
                      f.channel().closeFuture().sync();

                  } finally {
                      eventLoopGroup.shutdownGracefully();
                  }


              }

          }


          2.4.2 HttpClientBusinessHandler

          @Slf4j
          public class HttpClientBusinessHandler extends ChannelInboundHandlerAdapter {

              @Override
              public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                  //通過編解碼器把byteBuf解析成FullHttpResponse
                  if (msg instanceof FullHttpResponse) {
                      FullHttpResponse httpResponse = (FullHttpResponse) msg;
                      HttpResponseStatus status = httpResponse.status();
                      ByteBuf content = httpResponse.content();
                      log.info("客戶端接收響應信息:");
                      log.info("status:{},content:{}", status, content.toString(CharsetUtil.UTF_8));
                      httpResponse.release();
                  }
              }

              @Override
              public void channelActive(ChannelHandlerContext ctx) throws Exception {

                  //封裝請求信息
                  URI uri = new URI("/test");
                  String msg = "Hello";
                  DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1,
                          HttpMethod.GET, uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes(CharsetUtil.UTF_8)));

                  //構建http請求
                  request.headers().set(HttpHeaderNames.HOST, HttpConsts.HOST);
                  request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                  request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes());

                  // 發(fā)送http請求
                  ctx.writeAndFlush(request);
              }
          }

          2.4.3 HttpClientHandlerInitial

          public class HttpClientHandlerInitial extends ChannelInitializer<SocketChannel> {

              @Override
              protected void initChannel(SocketChannel ch) throws Exception {

                  ChannelPipeline pipeline = ch.pipeline();

                  //客戶端編碼、解碼器,請求編碼,響應解碼
                  pipeline.addLast("clientCodec", new HttpClientCodec());
                  //http聚合器,將http請求聚合成一個完整報文
                  pipeline.addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024));
                  //http響應解壓縮
                  pipeline.addLast("decompressor", new HttpContentDecompressor());
                  //業(yè)務handler
                  pipeline.addLast("clientBusinessHandler", new HttpClientBusinessHandler());

              }
          }


          2.5 測試

          啟動服務端:



          啟動客戶端:



          ————————————————

          版權聲明:本文為CSDN博主「你攜秋月攬星河丶」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權協(xié)議,轉載請附上原文出處鏈接及本聲明。

          原文鏈接:

          https://blog.csdn.net/qq_34125999/article/details/115488543





          鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布

          ??????

          ??長按上方微信二維碼 2 秒





          感謝點贊支持下哈 

          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩免费A片 | 日本黄色视频一级 | 天天做夜夜爱 | 狼人亚洲 | 黄色片三级片在线看网站 |