解决用netty去做web服务时,post长度过大的问题
原文地址
http://my.oschina.net/momohuang/blog/114552
先说一下,本来是想自己写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过来的数据,然后在整合起来,即可
解决用netty去做web服务时,post长度过大的问题的更多相关文章
- idea 为模块添加Tomcat依赖 解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包
解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包 今天创建SpringMVC项目时 用到HttpServletRequest时, 发现项目中根本没有Servlet这个包, ...
- 解决: Intelij IDEA 创建WEB项目时没有Servlet的jar包
今天创建SpringMVC项目时 用到HttpServletRequest时, 发现项目中根本没有Servlet这个包, 在网上搜了一下,这个问题是因为web项目没有添加服务器导致的. 配置tomec ...
- 解决eclipse中运行web项目时弹出的"Port 8080 required by Tomcat 9.0 Server at localhost is already in use...
1.tomcat默认端口是8080,可以修改通过tomcat的端口 修改tomcat\conf\server.xml 结果运行程序,还是报"Port 8080 required by ...
- ASP.NET Web服务调用发生错误,错误代码404
现象: iOS端使用ASIHTTP连接Web服务时,得到的数据是一个错误代码为404的页面,错误信息(web.config添加<customErrors mode="Off" ...
- 服务设计模式一:Web服务概述
目录 1. Web服务是什么 2.为什么要使用Web服务 3.Web服务考虑的因素和替代方案 4.SOA是什么 Web服务是什么? 所谓服务,通俗的理解就是别人帮你做一些事情,比如说,腰酸背痛了,找个 ...
- Web服务端性能提升实践
随着互联网的不断发展,日常生活中越来越多的需求通过网络来实现,从衣食住行到金融教育,从口袋到身份,人们无时无刻不依赖着网络,而且越来越多的人通过网络来完成自己的需求. 作为直接面对来自客户请求的Web ...
- Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)
一,Nginx基本安全优化 1.1 调整参数隐藏Nginx软件版本号信息 一般来说,软件的漏洞都和版本有关,这个很像汽车的缺陷,同一批次的要有问题就都有问题,别的批次可能就都是好的.因此,我们应尽量隐 ...
- 踩坑踩坑之Flask+ uWSGI + Tensorflow的Web服务部署
一.简介 作为算法开发人员,在算法模块完成后,拟部署Web服务以对外提供服务,从而将算法模型落地应用.本文针对首次基于Flask + uWSGI + Tensorflow + Nginx部署Web服务 ...
- Python Web 服务开发者: 第 1 部分
Python Web 服务开发者: 第 1 部分 Python Web 服务世界 Python 的座右铭一向是“装备齐全”,这是指在安装该语言时会附带一大套标准库和功能程序.本文概述了在 Python ...
- 利用OpenShift托管Node.js Web服务进行微信公众号开发
最近写了一个微信的翻译机器人.用户只要关注该公众号,发送英文的消息,就能收到中文翻译的回复.有兴趣的读者可以扫描下面的二维码关注该公众号,尝试发送英文单词试试看.(有时候第一次发送单词会收到“该公众号 ...
随机推荐
- iOS中搜索框EVNCustomSearchBar使用小结
最近在项目开发中用到了搜索框,之前都是用的系统的searchbar,现有项目中用的是EVNCustomSearchBar,我试了一下还挺方便,下面说一下具体的用法. 第一步:引入添加相关的委托代理EV ...
- yarn : 无法加载文件 C:\Users\zhulo\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?Li nkID=135170 中的 about_Execution_Policies。 所在位置 行:1 字符: 1 + yarn serve
powershell的执行策略问题: 解决办法: 管理员身份打开powershell 输入 set-ExecutionPolicy RemoteSigned 然后选择 a or Y :
- 16收16发ARINC429模块
6通道发送, 16通道接收* 发送通道:每路发送通道FIFO大小为:511 x 32bit(CHR32216/32316) ,缓存256条发送消息(CHR32216-EX/32316-EX)发送FIF ...
- C#使用Kubernetes (k8s)
在C#中使用Kubernetes (k8s) 通常通过官方的Kubernetes .NET客户端与Kubernetes API进行交互.以下是如何在C#中使用Kubernetes的简要指南. 1. 安 ...
- Windows 如何启用 Administrator 账户
Windows 默认安装的时候需要自己定义一个账户,不是管理员账户,不能操作某些目录,有时很不方便.不过我们可以手动打开,像盗版一样默认使用 Administrator 账户: 按下Win + R, ...
- NIO聊天室
SocketChannel 和 ServerSocketChannel ServerSocketChannel 用于创建服务器端套接字,而 SocketChannel 用于创建客户端套接字.它们都支持 ...
- Machine Learning Week_1 Linear Algebra Review 1-6
目录 4 Linear Algebra Review 4.1 Video: Matrices and Vectors unfamiliar words 4.2 Reading: Matrices an ...
- 鸿蒙NEXT应用上架与分发步骤详解
大家好,我是 V 哥.今天的文章来聊一聊HarmonyOS NEXT应用上架.当你开发.调试完HarmonyOS应用/元服务,就可以前往AppGallery Connect申请上架,华为审核通过后,用 ...
- Power BI如何连接MySQL数据库
既然写了如何卸载MySQL connector net(相关文章见如何解决MySQL Connector NET xxxx无法卸载的问题(win10)),那就顺便再写一篇Power BI(以下简称PB ...
- 认识鸿蒙Context
Context是应用中对象的上下文,其提供了应用的一些基础信息,例如resourceManager(资源管理).applicationInfo(当前应用信息).dir(应用文件路径).area(文件分 ...