文档章节

解决用netty去做web服务时,post长度过大的问题

momoHuang
 momoHuang
发布于 2013/03/18 21:31
字数 752
阅读 6572
收藏 44

先说一下,本来是想自己写socket ,启动一个简单点的web服务用于接收数据的。写完之后,发现会有各种情况没有考虑到的,很有可能出现问题,而且,太折腾了。于是,就用了netty去其web服务,另外,我也觉得netty基本上是最简单的web服务了吧,如果童鞋们有其他推荐的话,就留个言呗。

1、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端口。


2、当客户端给服务端post数据的时候,如果数据超过50K,这个时候服务端接受到的post内容是空的了。这是因为超过了 服务端默认的post的长度的最大值。

http协议里边,本来是没有对post的长度进行限制,但是,无论是系统层面或者是服务端层面的,都会对post的长度进行限制,这个也有利于网络安全。

3、在netty中的解决方法


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;
		}
	}
加上


pipeline.addLast("aggregator", new HttpChunkAggregator(65536))
之后,设置默认的chunk最大为 65536,这样,就可以接受最大post的内容大小为 65536。


这样有一个不好的地方,就是这个大小不好控制,开大了,会浪费空间。并且在接受到的字符串的最后,会出现空白的字符串,这是由于post的内容长度小于chunk里边的ChannelBuffer的数组的大小,程序给予补全。

4、自己设置,自己读取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过来的数据,然后在整合起来,即可


© 著作权归作者所有

momoHuang
粉丝 4
博文 24
码字总数 10538
作品 0
深圳
私信 提问
加载中

评论(10)

钱亮亮
钱亮亮
能给出handle代码吗?
momoHuang
momoHuang

引用来自“se77en.cc”的评论

http://spray.io/

建议写个简单的教程
momoHuang
momoHuang

引用来自“专业打酱油”的评论

引用来自“se77en.cc”的评论

http://spray.io/

感觉不错

很轻便?
JavaGG
JavaGG
一直在用netty,不过没有试过用来做业务上的http服务器
后台管理倒用过
麦麸子lee
麦麸子lee
呵呵,正想试用netty
专业打酱油
专业打酱油

引用来自“se77en.cc”的评论

http://spray.io/

感觉不错
se77en
se77en
http://spray.io/
专业打酱油
专业打酱油

引用来自“Burning_BL”的评论

引用来自“专业打酱油”的评论

jetty

你是认真的吗?netty和mina都是网络通信框架,jetty是servlet容器好吗。

难道jetty不能做web服务吗?
铂金小虫
铂金小虫

引用来自“专业打酱油”的评论

jetty

你是认真的吗?netty和mina都是网络通信框架,jetty是servlet容器好吗。
专业打酱油
专业打酱油
jetty
用Netty 作为server端实现,客户端实现没有采用netty,出现问题:数据包过大,服务端无法完整接收数据包!

最近对Netty作了一些尝试,随意写了一个服务端,然后用tcp软件 发送 数据给 服务端,发现一个问题: 当发送数据过大时,服务端就不能完整接收数据了,请问大侠们 如何解决这个问题的! 另:网...

sunvim
2014/01/01
1K
6
netty websocket通讯接收数据不完整问题!

最近在做一个java web项目,里面需要集成netty websocket。java web项目作为服务器端已经完全可以和客户端进行数据通信。但是存在一个问题,当客户端向服务器端发送一个超长json串时候,提示...

Daisygeo
2018/05/28
819
2
netty多线程通信一次传输较大数据遇到的问题

您好,刚入门netty,想请教大神们几个问题,对于只有一个线程一次传输过大的数据,通过这个方法解决了:传输时头4个字节保存数据大小,后面保存内容,接收时如果发现读取的数据长度不够,则累...

oOjackOo
2015/04/02
4.1K
3
【Netty】Netty实例开源项目

版权声明:本文为谙忆原创文章,转载请附上本文链接,谢谢。 https://blog.csdn.net/qq_26525215/article/details/81989644 Netty netty-not-sticky-pack-demo 项目地址 Netty 本篇博客讲解:...

谙忆
2018/08/23
0
0
结合RPC框架通信谈 netty如何解决TCP粘包问题

0.起因 因为自己造一个RPC框架的轮子时,需要解决TCP的粘包问题,特此记录,希望方便他人。这是我写的RPC框架的 GitHub地址 https://github.com/yangzhenkun/krpc。 欢迎star,fork。已经写了...

JAVA高级架构v
2018/08/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

好文:华杉:我等用功,不求日增,但求日减。减一分人欲,则增一分天理,这是何等简易!何等洒脱!

#写在前面1.怎么理解“减一分人欲,则增一分天理,这是何等简易!”?1)华杉提倡 “一劳永逸” 排除浪费,少干活,多赚钱,一战而定,降低作业成本。2)华杉提倡学海无涯,回头是岸...

阿锋zxf
14分钟前
1
0
vue 的bus总线

bus声明 global.bus = new Vue() 事件发送 controlTabbar () {global.bus.$emit('pickUp', 'ddd')}, 事件接收 global.bus.$on('pickUp', (res) => {this.isFocus = true})......

Js_Mei
19分钟前
2
0
大型系统演进之路-负载均衡演进

Nginx做负载均衡 通过Nginx的反向代理将请求分发到tomcat中,如果tomcat支持100并发,Nginx支持50000并发,理论上nginx把请求发送到500个tomcat就可以了。 LVS或F5做多个Nginx负载均衡 Tomc...

春哥大魔王的博客
24分钟前
4
0
Sqlite时间段查询中遇到的问题

问题: 我要查询DateTime时间其中的一段符合时间要求的数据,比如我要查询‘2019-06-06 16:50:00’至‘2019-06-06 16:59:00’这一段的数据 开始用这段代码 strSql= ("select * from Coll...

rainbowcode
28分钟前
2
0
大数据(hadoop-数据入库系统Sqoop原理架构)

Sqoop是什么 Sqoop:SQL-to-Hadoop 连接传统关系型数据库和Hadoop的桥梁 把关系型数据库的数据导入到 Hadoop 系统 ( 如 HDFS、HBase 和 Hive) 中; 把数据从 Hadoop 系统里抽取并导出到关系型...

这很耳东先生
43分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部