All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mars.iserver.server.helper.MarsHttpHelper Maven / Gradle / Ivy

There is a newer version: 3.3.3
Show newest version
package com.mars.iserver.server.helper;

import com.mars.common.annotation.enums.ReqMethod;
import com.mars.common.base.config.model.RequestConfig;
import com.mars.common.constant.MarsConstant;
import com.mars.common.util.MarsConfiguration;
import com.mars.common.util.MesUtil;
import com.mars.common.util.StringUtil;
import com.mars.iserver.constant.HttpConstant;
import com.mars.iserver.server.MarsServerHandler;
import com.mars.iserver.server.factory.MarsServerHandlerFactory;
import com.mars.iserver.server.impl.MarsHttpExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * Http注册,读取,写入 帮助类
 */
public class MarsHttpHelper {

    private static Logger log = LoggerFactory.getLogger(MarsHttpHelper.class);

    /**
     * 每次从通道读多少字节
     */
    private static int readSize;

    /**
     * 读取超时时间
     */
    private static int readTimeout;

    /**
     * 初始化
     */
    private static void init(){
        RequestConfig requestConfig = MarsConfiguration.getConfig().requestConfig();
        readSize = requestConfig.getReadSize();
        readTimeout = requestConfig.getReadTimeout();
    }

    /**
     * 注册成可读状态
     * @param selector
     * @param selectionKey
     */
    public static void acceptable(Selector selector, SelectionKey selectionKey){
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
        SocketChannel socketChannel = null;
        try {
            socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } catch (IOException e) {
            log.error("注册SocketChannel异常", e);
            close(socketChannel, selectionKey);
        }
    }

    /**
     * 读取数据并创建MarsHttpExchange对象
     */
    public static void read(Selector selector, SelectionKey selectionKey) {
        if(readSize <= 0 || readTimeout <= 0){
            init();
        }

        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        MarsHttpExchange marsHttpExchange = getMarsHttpExchange(socketChannel, selector, selectionKey);

        /* 一开始需要先读取请求头,所以这里要设置小一点,防止读出过多的数据*/
        ByteBuffer readBuffer = ByteBuffer.allocate(800);
        readBuffer.clear();

        try {
            /* 用来储存从socketChannel读出来的数据 */
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            /* 是否已经读完head了 */
            boolean readHead = false;
            /* head的长度,用来计算body长度 */
            int headLength = 0;
            /* 内容长度 */
            long contentLength = -1;
            /* 开始读取时间 */
            long start = System.currentTimeMillis();

            /* 开始读数据 */
            while (socketChannel.read(readBuffer) > -1) {
                /* 计算是否超时 */
                isReadTimeout(start);

                /* 获取请求报文 */
                byte[] bytes = getReadData(readBuffer);
                /* 将本次读取到的数据追加到输出流 */
                outputStream.write(bytes);

                if(!readHead){
                    String headStr = new String(outputStream.toByteArray());
                    /* 判断是否已经把头读完了,如果出现了连续的两个换行,则代表头已经读完了 */
                    int headEndIndex = headStr.indexOf(HttpConstant.HEAD_END);
                    if(headEndIndex < 0){
                        continue;
                    }

                    /* 解析头并获取头的长度 */
                    headLength = parseHeader(headStr, headEndIndex, marsHttpExchange);
                    readHead = true;
                    /* 如果头读完了,并且此次请求是GET,则停止 */
                    if(marsHttpExchange.getRequestMethod().toUpperCase().equals(ReqMethod.GET.toString())){
                        break;
                    }

                    /* 从head获取到Content-Length */
                    contentLength = marsHttpExchange.getRequestContentLength();
                    if(contentLength < 0){
                        break;
                    }

                    /* 当请求头读完了以后,并且本次请求不是get, 就加大每次读取大小 加快速度 */
                    readBuffer = ByteBuffer.allocate(readSize);
                    readBuffer.clear();
                } else {
                    /* 判断已经读取的body长度是否等于Content-Length,如果条件满足则说明读取完成 */
                    int streamLength = outputStream.size();
                    if((streamLength - headLength) >= contentLength){
                        break;
                    }
                }
            }

            /* 从报文中获取body */
            getBody(outputStream, headLength, marsHttpExchange);

            /* 过滤掉非法读取 */
            if(marsHttpExchange.getRequestURI() == null
                    || marsHttpExchange.getRequestMethod() == null
                    || marsHttpExchange.getHttpVersion() == null) {
                close(socketChannel, selectionKey);
                return;
            }

            /* 注册成可写状态 */
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_WRITE, marsHttpExchange);

        } catch (Exception e) {
            log.error("处理请求异常", e);
            errorResponseText(e, marsHttpExchange);
            close(socketChannel, selectionKey);
        }
    }

    /**
     * 获取处理对象
     * @param socketChannel
     * @param selector
     * @param selectionKey
     * @return
     */
    private static MarsHttpExchange getMarsHttpExchange(SocketChannel socketChannel, Selector selector, SelectionKey selectionKey){
        MarsHttpExchange marsHttpExchange = new MarsHttpExchange();
        marsHttpExchange.setSocketChannel(socketChannel);
        marsHttpExchange.setSelectionKey(selectionKey);
        marsHttpExchange.setSelector(selector);
        return marsHttpExchange;
    }

    /**
     * 读取数据
     * @param readBuffer
     * @return
     */
    private static byte[] getReadData(ByteBuffer readBuffer){
        readBuffer.flip();
        byte[] bytes = new byte[readBuffer.limit()];
        readBuffer.get(bytes);
        readBuffer.clear();
        return bytes;
    }

    /**
     * 是否超时了
     * @param start
     * @throws Exception
     */
    private static void isReadTimeout(long start) throws Exception {
        long end = System.currentTimeMillis();
        if((end - start) > readTimeout){
            throw new Exception("读取请求数据超时");
        }
    }

    /**
     * 读取请求头
     * @throws Exception
     */
    private static int parseHeader(String headStr, int headEndIndex, MarsHttpExchange marsHttpExchange) throws Exception {
        headStr = headStr.substring(0, headEndIndex);

        String[] headers = headStr.split(HttpConstant.CARRIAGE_RETURN);
        for(int i=0;i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy