public class HttpServer {
public void start(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
int availProcessors = Runtime.getRuntime().availableProcessors();
EventLoopGroup workerGroup = new NioEventLoopGroup(availProcessors*2);
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
//对http消息编解码
ch.pipeline().addLast(new HttpServerCodec());
//合并HttpMessage和HttpContent,构成FullHttpRequest或者FullHttpResponse
ch.pipeline().addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
//支持大数据包发送,支持发送chunk块,支持HTTP协议的chunked编码
ch.pipeline().addLast(new ChunkedWriteHandler());
ch.pipeline().addLast(new UserHandler());
}
}).option(ChannelOption.SO_BACKLOG, 1024) //存放请求的缓冲队列的大小
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.SO_SNDBUF,1024*1024*32)
.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK,1024*1024*32)
.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK,1024*1024*24);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
}catch (InterruptedException e){
e.printStackTrace();
}
finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
HttpServer server = new HttpServer();
server.start(9999);
}
}
//FullHttpRequest是由于pipeline使用了HttpObjectAggregator
public class UserHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
//--------------------------获取请求ip-----------------------------------------
String clientIP = request.headers().get("X-Forwarded-For");
if (clientIP == null) {
InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
clientIP = insocket.getAddress().getHostAddress();
}
//------------解析get请求参数:http://ip:port/path?key1=value1&key2=value2------
QueryStringDecoder decoder = new QueryStringDecoder(request.getUri());
String path = decoder.path();
Map<String, List<String>> params = decoder.parameters();
//---------------------------解析post请求参数-----------------------------------
String contentType = request.headers().get("Content-Type");
if(contentType.equals("application/json")){
String jsonStr = request.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
Map params = JSON.parseObject(jsonStr,Map.class);
for(Object key : params.keySet()){
System.out.println(key + " " + params.get(key));
}
}else if(contentType.equals("application/x-www-form-urlencoded")){
String content = request.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(content,false);
Map<String, List<String>> params = queryStringDecoder.parameters();
for(Map.Entry<String,List<String>> entry : params.entrySet()){
System.out.println(entry.getKey() + ":" + entry.getValue().get(0));
}
}else if(contentType.startsWith("multipart/form-data")){
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, Charsets.toCharset(CharEncoding.UTF_8));
List<InterfaceHttpData> datas = decoder.getBodyHttpDatas();
System.out.println("enter 1");
for(InterfaceHttpData data : datas){
System.out.println("enter 2");
System.out.println(data.getHttpDataType());
if(data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
System.out.println("enter 3");
FileUpload fileUpload = (FileUpload) data;
System.out.println(fileUpload.content().toString(Charsets.toCharset(CharEncoding.UTF_8)));
}
}
}
//------------------------响应请求--------------------------------------------
Map<String, Object> res = new HashMap<>();
res.put("message", "done success");
res.put("code", 0);
String resJsonStr = JSON.toJSONString(res);
ByteBuf content = copiedBuffer(resJsonStr, CharsetUtil.UTF_8);
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status,content);
HttpHeaders.setContentLength(response,content.readableBytes());
response.headers().set(CONTENT_TYPE,APPLICATION_JSON);
ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
//------------------------响应请求,http chunked编码---------------------------
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
HttpHeaders.setTransferEncodingChunked(response); //指定chunked编码
if (HttpHeaders.isKeepAlive(request)) {
response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
}
ctx.write(response);
//cbInputStream是一个InputStream
ctx.write(new HttpChunkedInput(new ChunkedStream(cbInputStream, 1024 * 32)), ctx.newProgressivePromise());
ChannelFuture lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
if (!HttpHeaders.isKeepAlive(request)) {
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
}
}