zoukankan      html  css  js  c++  java
  • netty搭建http服务器

    public class HttpServerStart {
        public static volatile boolean flag = false ;
        public static void start() {
            int port = 8099;
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .handler(new LoggingHandler(LogLevel.INFO))
                        .childHandler(new HttpServerInitializer())
                        .option(ChannelOption.SO_BACKLOG, 1024)
                        .childOption(ChannelOption.SO_KEEPALIVE, true);
    
                Channel ch = b.bind(port).sync().channel();
                System.out.println("httpserver服务成功启动,请打开 http://127.0.0.1:" + port);
                flag = true ;
                ch.closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
    public class HttpServerInitializer  extends ChannelInitializer<SocketChannel> {
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            //HttpObjectAggregator HTTP 消息解码器, 作用时将多个消息转换为1个FullHttpRequest 或者 FullHttpResponse 对象
            /**
             * HttpRequestDecoder 会将每个 HTTP 消息转换为 多个消息对象
             * HttpResquest / HttpResponse
             * HttpContent
             * LastHttpContent
             */
            //将请求和应答消息编码或解码为HTTP消息
            socketChannel.pipeline().addLast(new HttpRequestDecoder());
            socketChannel.pipeline().addLast(new HttpObjectAggregator(65536));// 目的是将多个消息转换为单一的request或者response对象
            socketChannel.pipeline().addLast(new HttpResponseEncoder());
            socketChannel.pipeline().addLast(new ChunkedWriteHandler());//目的是支持异步大文件传输()
            socketChannel.pipeline().addLast("file-handler", new FileServerHandler());
            socketChannel.pipeline().addLast("handler", new HttpServerHandler(false));
        }
    }
    public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.flush();
        }
    
    
        public HttpServerHandler(boolean isAutoRelease){
            super(isAutoRelease);
        }
    
    
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) throws Exception {
            try {
                if(!request.decoderResult().isSuccess()){
                    DonkeyHttpUtil.writeResponse(request, BAD_REQUEST, channelHandlerContext);
                    return;
                }
                if(request.method() != HttpMethod.GET){
                    DonkeyHttpUtil.writeResponse(request, METHOD_NOT_ALLOWED, channelHandlerContext);
                    return;
                }
                DonkeyHttpUtil.writeResponse(request, OK, channelHandlerContext);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    }
    public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    
    
    
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) throws Exception {
            //request.retain();
            HttpResponse response = null;
            RandomAccessFile randomAccessFile = null;
            try{
                // 状态为1xx的话,继续请求
                if (HttpHeaders.is100ContinueExpected(request)) {
                    send100Continue(channelHandlerContext);
                }
                String uri = request.uri();//   /digitalPlatform/common/common.js
                if(!uri.endsWith(".js")
                        && !uri.endsWith(".css")
                        && !uri.endsWith(".html")
                        && !uri.endsWith(".png")
                        && !uri.endsWith(".jpg")
                        && !uri.endsWith(".gif")){
                    channelHandlerContext.fireChannelRead(request);
                    return;
                }
                uri = uri.substring(1);
                InputStream input = MyApplication.getApplication().getAssets().open(uri);
                File f = new File
                        (Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "cloudsapp"+File.separator+uri);
    
                if (f.exists()) {
                    f.delete();
                }else{
                    f.getParentFile().mkdirs();
                }
                f.createNewFile();
                byte[] bytes = new byte[input.available()];
                input.read(bytes);
    
                OutputStream os = new FileOutputStream(f);
                BufferedOutputStream bos = new BufferedOutputStream(os);
                bos.write(bytes);
                bos.flush();
                bos.close();
    
               try {
                    randomAccessFile = new RandomAccessFile(f, "r");
                } catch (FileNotFoundException e) {
                    DonkeyHttpUtil.writeResponse(request, NOT_FOUND, channelHandlerContext);
                    e.printStackTrace();
                    return;
                }
    
                if(!f.exists() || f.isHidden()){
                    DonkeyHttpUtil.writeResponse(request, NOT_FOUND, channelHandlerContext);
                    return;
                }
                long fileLength = randomAccessFile.length();
                response = new DefaultHttpResponse(request.protocolVersion(), HttpResponseStatus.OK);
    
                setContentType(response, f);
                boolean keepAlive =  HttpUtil.isKeepAlive(request);
                if (keepAlive) {
                    response.headers().set(HttpHeaderNames.CONTENT_LENGTH, fileLength);
                    response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                }
                channelHandlerContext.write(response);
    
    
                ChannelFuture sendFileFuture = channelHandlerContext.write(new ChunkedNioFile(randomAccessFile.getChannel()), channelHandlerContext.newProgressivePromise());
                // 写入文件尾部
                sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
                    @Override
                    public void operationProgressed(ChannelProgressiveFuture future,
                                                    long progress, long total) {
                        if (total < 0) { // total unknown
                            System.out.println("Transfer progress: " + progress);
                        } else {
                            System.out.println("Transfer progress: " + progress + " / "
                                    + total);
                        }
                    }
    
                    @Override
                    public void operationComplete(ChannelProgressiveFuture future)
                            throws Exception {
                        System.out.println("Transfer complete.");
                    }
    
    
                });
                ChannelFuture lastContentFuture =  channelHandlerContext.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
                if (!keepAlive) {
                    lastContentFuture.addListener(ChannelFutureListener.CLOSE);
                }
            }catch (Exception e){
                DonkeyHttpUtil.writeResponse(request, NOT_FOUND, channelHandlerContext);
                e.printStackTrace();
            }finally {
                if(randomAccessFile != null){
                    try {
                        randomAccessFile.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else{
                    DonkeyHttpUtil.writeResponse(request, NOT_FOUND, channelHandlerContext);
                }
            }
        }
    
    
        public static void writeBytesToFile(InputStream is, File file) throws IOException{
            FileOutputStream fos = null;
            try {
                byte[] data = new byte[2048];
                int nbread = 0;
                fos = new FileOutputStream(file);
                while((nbread=is.read(data))>-1){
                    fos.write(data,0,nbread);
                }
            }
            catch (Exception ex) {
                Log.e("Exception",ex.getMessage());
            }
            finally{
                if (fos!=null){
                    fos.close();
                }
            }
        }
        private void setContentType(HttpResponse response, File file){
            //MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
            if(file.getName().endsWith(".js")){
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/x-javascript");
            }else if(file.getName().endsWith(".css")){
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/css; charset=UTF-8");
            }else if (file.getName().endsWith(".html")){
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
            }
        }
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    
        private static void send100Continue(ChannelHandlerContext ctx) {
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
            ctx.writeAndFlush(response);
        }
    }
    public class DonkeyHttpUtil {
    
    
        public static boolean writeResponse(FullHttpRequest request, HttpResponseStatus status, ChannelHandlerContext ctx) {
            // Decide whether to close the connection or not.
            boolean keepAlive = HttpUtil.isKeepAlive(request);
            // Build the response object.
            FullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), status,
                    Unpooled.copiedBuffer(status.toString(), CharsetUtil.UTF_8));
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
            if (keepAlive) {
                // Add 'Content-Length' header only for a keep-alive connection.
                response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
                // Add keep alive header as per:
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
            }
    
            // Encode the cookie.
            String cookieString = request.headers().get(HttpHeaderNames.COOKIE);
            if (cookieString != null) {
                Set<io.netty.handler.codec.http.cookie.Cookie> cookies = ServerCookieDecoder.STRICT.decode(cookieString);
                if (!cookies.isEmpty()) {
                    // Reset the cookies if necessary.
                    for (io.netty.handler.codec.http.cookie.Cookie cookie : cookies) {
                        response.headers().add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie));
                    }
                }
            }
            // Write the response.
            ctx.write(response);
            return keepAlive;
        }
    }
  • 相关阅读:
    java 编码分析
    httpclient
    http://www.cognoschina.net/club/
    (原创)冬日里的一抹暖(摄影,欣赏)
    (原创)Louis Aston Knight 的家(摄影,欣赏)
    (原创)微笑佛国(摄影,欣赏)
    (原创)黑白风景(摄影,欣赏)
    (原创)浪迹天涯的哈士奇(摄影,欣赏)
    (转载)天山公路(摄影,欣赏)
    (原创)巩固理解基于DS18B20的1-wire协议(MCU,经验)
  • 原文地址:https://www.cnblogs.com/syscn/p/14506196.html
Copyright © 2011-2022 走看看