
com.mars.iserver.server.helper.MarsHttpHelper Maven / Gradle / Ivy
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