原文地址java
http://my.oschina.net/momohuang/blog/114552 web
先說一下,原本是想本身寫socket ,啓動一個簡單點的web服務用於接收數據的。寫完以後,發現會有各類狀況沒有考慮到的,頗有可能出現問題,並且,太折騰了。因而,就用了netty去其web服務,另外,我也以爲netty基本上是最簡單的web服務了吧,若是童鞋們有其餘推薦的話,就留個言唄。bootstrap
一、server
數組
public class AdminServer { protected static final Log log = LogFactory.getLog(AdminServer.class); public static void main(String[] args) { log.info("start app"); start(8088); // System.out.println("admin start on "+1); } public static void start(int port) { // 配置服務器-使用java線程池做爲解釋線程 ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // 設置 pipeline factory. bootstrap.setPipelineFactory(new ServerPipelineFactory()); // 綁定端口 bootstrap.bind(new InetSocketAddress(port)); System.out.println("admin start on "+port); ServiceLocator.initServiceLocator(); } private static class ServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("encoder", new HttpResponseEncoder()); //http處理handler pipeline.addLast("handler", new AdminServerHandler()); return pipeline; } } }
啓動了服務,綁定了8088端口。安全
二、當客戶端給服務端post數據的時候,若是數據超過50K,這個時候服務端接受到的post內容是空的了。這是由於超過了 服務端默認的post的長度的最大值。服務器
http協議裏邊,原本是沒有對post的長度進行限制,可是,不管是系統層面或者是服務端層面的,都會對post的長度進行限制,這個也有利於網絡安全。
網絡
三、在netty中的解決方法app
private static class ServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = Channels.pipeline(); // pipeline.addFirst("frameDecoder", new LengthFieldBasedFrameDecoder(100000000,0,4,0,4)); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("encoder", new HttpResponseEncoder()); // pipeline.addLast("streamer", new ChunkedWriteHandler()); pipeline.addLast("aggregator", new HttpChunkAggregator(65536));//設置塊的最大字節數 //http處理handler pipeline.addLast("handler", new AdminServerHandler()); return pipeline; } }
加上socket
pipeline.addLast("aggregator", new HttpChunkAggregator(65536))
以後,設置默認的chunk最大爲 65536,這樣,就能夠接受最大post的內容大小爲 65536。ide
這樣有一個很差的地方,就是這個大小很差控制,開大了,會浪費空間。而且在接受到的字符串的最後,會出現空白的字符串,這是因爲post的內容長度小於chunk裏邊的ChannelBuffer的數組的大小,程序給予補全。
四、本身設置,本身讀取chunk
加上
pipeline.addLast("streamer", new ChunkedWriteHandler());
設置爲給位 分開一個個chunk去接受信息。
public boolean excuteChunk(ChannelHandlerContext ctx, MessageEvent e) throws TooLongFrameException { // HttpMessage currentMessage = e.getMessage(); if (e.getMessage() instanceof HttpMessage) { HttpMessage m = (HttpMessage) e.getMessage(); if (m.isChunked()) { // A chunked message - remove 'Transfer-Encoding' header, // initialize the cumulative buffer, and wait for incoming // chunks. List<String> encodings = m .getHeaders(HttpHeaders.Names.TRANSFER_ENCODING); encodings.remove(HttpHeaders.Values.CHUNKED); if (encodings.isEmpty()) { m.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING); } m.setContent(ChannelBuffers.dynamicBuffer(e.getChannel() .getConfig().getBufferFactory())); this.currentMessage = m; } else { // Not a chunked message - pass through. this.currentMessage = null; } return false; } else if (e.getMessage() instanceof HttpChunk) { // Sanity check if (currentMessage == null) { throw new IllegalStateException("received " + HttpChunk.class.getSimpleName() + " without " + HttpMessage.class.getSimpleName()); } // Merge the received chunk into the content of the current message. HttpChunk chunk = (HttpChunk) e.getMessage(); ChannelBuffer content = currentMessage.getContent(); if (content.readableBytes() > maxContentLength - chunk.getContent().readableBytes()) { throw new TooLongFrameException("HTTP content length exceeded " + maxContentLength + " bytes."); } content.writeBytes(chunk.getContent()); if (chunk.isLast()) { this.currentMessage = null; currentMessage.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(content.readableBytes())); return true; // Channels.fireMessageReceived(ctx, currentMessage, // e.getRemoteAddress()); } } return true; }
在handle中,本身作處理,接受 整個post過來的數據,而後在整合起來,便可