基于Netty的http服务器

根据netty一个官方例子改编

 

//html文件位置
public class Config {
    public static String getRealPath(String uri) {
        StringBuilder sb=new StringBuilder("E:/htmlDemo");
        sb.append(uri);
        if (!uri.endsWith("/")) {
            sb.append('/');
        }
        return sb.toString();
    }
}
//根据url获取html资源
public class HttpServerHandler2  extends SimpleChannelInboundHandler<Object> {
 private HttpRequest request;
 private boolean readingChunks; 
 private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); //Disk
   
    private HttpPostRequestDecoder decoder;
 
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        if (decoder != null) {
            decoder.cleanFiles();
        }
    }
    
 @Override
 public void channelReadComplete(ChannelHandlerContext ctx){
  ctx.flush();
  System.out.println("channelReadComplete");
 }
 
 
 @Override
 protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
  if (msg instanceof HttpRequest) {
            HttpRequest request = this.request = (HttpRequest) msg;
            
            if (HttpHeaderUtil.is100ContinueExpected(request)) {
                send100Continue(ctx);
            }
            HttpHeaders headers = request.headers();
            if (!headers.isEmpty()) {
                for (Map.Entry<CharSequence, CharSequence> h: headers) {
                    CharSequence key = h.getKey();
                    CharSequence value = h.getValue();
                    
                }
              
            }
            QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri());
            Map<String, List<String>> params = queryStringDecoder.parameters();
            if (!params.isEmpty()) {
                for (Entry<String, List<String>> p: params.entrySet()) {
                    String key = p.getKey();
                    List<String> vals = p.getValue();
                    for (String val : vals) {
                       
                    }
                }
                
            }
            try {
                decoder = new HttpPostRequestDecoder(factory, request);
            } catch (ErrorDataDecoderException e1) {
                e1.printStackTrace();
                //writeResponse(ctx.channel());
                ctx.channel().close();
                return;
            }
            readingChunks = HttpHeaderUtil.isTransferEncodingChunked(request);
            System.out.println("Is Chunked: " + readingChunks + "\r\n");
            System.out.println("IsMultipart: " + decoder.isMultipart() + "\r\n");
            if (readingChunks) {
                // Chunk version
             System.out.println("Chunks: ");
                readingChunks = true;
            }
        }
  if(decoder != null){
   if (msg instanceof HttpContent) {
     // New chunk is received
                HttpContent chunk = (HttpContent) msg;
                try {
                    decoder.offer(chunk);
                } catch (ErrorDataDecoderException e1) {
                    e1.printStackTrace();
                    //writeResponse(ctx.channel());
                    ctx.channel().close();
                    return;
                }
                System.out.println('o');
                
                //readHttpDataChunkByChunk();
                // example of reading only if at the end
                if (chunk instanceof LastHttpContent) {
                 String uri = this.request.uri();
                    System.out.println("-----------------------------------------------------------------");
                    System.out.println("uri:"+uri);
                    System.out.println("-----------------------------------------------------------------");
                   
                    writeResponse(ctx, uri);
                    readingChunks = false;
                    reset();
                }
         }
  }else {
            writeResponse(ctx, "/");
        }
               
    }
 
 
  private void reset() {
         request = null;
         // destroy the decoder to release all resources
         decoder.destroy();
         decoder = null;
  }
 private void writeResponse(ChannelHandlerContext ctx, String uri) {
        // 解析Connection首部,判断是否为持久连接
        boolean keepAlive = HttpHeaderUtil.isKeepAlive(request);
 
        // Build the response object.
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.setStatus(HttpResponseStatus.OK);
        // 服务端可以通过location首部将客户端导向某个资源的地址。
        // response.addHeader("Location", uri);
        if (keepAlive) {
            // Add 'Content-Length' header only for a keep-alive connection.
            response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        }
        // 得到客户端的cookie信息,并再次写到客户端
        String cookieString = request.headers().getAndConvert(HttpHeaderNames.COOKIE);
        if (cookieString != null) {
            Set<Cookie> cookies = ServerCookieDecoder.decode(cookieString);
            if (!cookies.isEmpty()) {
                // Reset the cookies if necessary.
                for (Cookie cookie: cookies) {
                    response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.encode(cookie));
                }
            }
        } else {
            // Browser sent no cookie.  Add some.
            response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.encode("key1", "value1"));
            response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.encode("key2", "value2"));
        }
        
        //文件路径
        final String path = (Config.getRealPath(uri));
        File localFile = new File(path);        
        // 如果文件隐藏或者不存在
        if (localFile.isHidden() || !localFile.exists()) {
            // 逻辑处理
         System.out.println("如果文件隐藏或者不存在");
         sendError(ctx, NOT_FOUND);
            return;
        }
        // 如果请求路径为目录
        if (localFile.isDirectory()) {
            // 逻辑处理
         System.out.println("如果请求路径为目录");
            return;
        }
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(localFile, "r");
            long fileLength = raf.length();            
            response.headers().setLong(HttpHeaderNames.CONTENT_LENGTH, fileLength);
            Channel ch = ctx.channel();
            ch.write(response);
            // 这里又要重新温习下http的方法,head方法与get方法类似,但是服务器在响应中只返回首部,不会返回实体的主体部分
            if (!request.method().equals(HttpMethod.HEAD)) {
             System.out.println("读文件");
                ch.write(new ChunkedFile(raf, 0, fileLength, 8192));//8kb
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        } finally {
            if (keepAlive) {
              response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
            }
            if (!keepAlive) {
                ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
            }
        } 
    }
 
 private void send100Continue(ChannelHandlerContext ctx) {
  FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
  ctx.write(response);
 }
 @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
 
 private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
  FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, status,
    Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n", CharsetUtil.UTF_8));
  response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
  ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
 } 
}

 

 

 
//服务运行类
public class HttpServer {

    public void run(final int port) throws Exception {
 EventLoopGroup bossGroup = new NioEventLoopGroup();
 EventLoopGroup workerGroup = new NioEventLoopGroup();
 try {
     ServerBootstrap b = new ServerBootstrap();
     b.group(bossGroup, workerGroup)
      .channel(NioServerSocketChannel.class)
      .childHandler(new ChannelInitializer<SocketChannel>() {
   @Override
   protected void initChannel(SocketChannel ch)
    throws Exception {
       ch.pipeline().addLast("http-decoder",
        new HttpRequestDecoder());
       ch.pipeline().addLast("http-aggregator",
        new HttpObjectAggregator(65536));
       ch.pipeline().addLast("http-encoder",
        new HttpResponseEncoder());
       ch.pipeline().addLast("http-chunked",
        new ChunkedWriteHandler());
       ch.pipeline().addLast("handler",
        new HttpServerHandler());
   }
      });
     ChannelFuture future = b.bind("192.168.1.10", port).sync();
     System.out.println("HTTP服务器启动,网址是 : " + "http://192.168.1.10:"
      + port);
     future.channel().closeFuture().sync();
 } finally {
     bossGroup.shutdownGracefully();
     workerGroup.shutdownGracefully();
 }
    }
    public static void main(String[] args) throws Exception {
 
     new HttpServer().run(8080);
    }

 

你可能感兴趣的:(基于Netty的http服务器)