DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

httpclient-4.5.9.jar

org.apache.http:

                     auth     身份

                     client    端

                     conn     连接

                     cookie  本地

                 impl:    实现

                     execchain   异常

 

httpcore-4.4.11.jar

org.apache.http.entity;

AbstractHttpEntity

http请求体包报文格式:

Content-Type:                  报文类型:application/json;charset=utf-8

Content-Encoding:            编码方式:gzip或deflate

Content-Length:               报文长度:

Chunked:                         是否分块传输

 

Content-Length, HTTP消息长度, 用十进制数字表示的八位字节的数目. 一般情况下, 很多工作都被框架完成, 我们很少去关注这部分内容, 但少数情况下发生了Content-Length与实际消息长度不一致, 程序可能会发生比较奇怪的异常, 如:

  • 无响应直到超时.
  • 请求被截断, 而且下一个请求解析出现错乱.

Content-Length是HTTP消息长度, 用十进制数字表示的八位字节的数目, 是Headers中常见的一个字段. Content-Length应该是精确的, 否则就会导致异常 (特别地, HTTP1.0中这个字段可有可无).

Content-Length首部指示出报文中实体主体的字节大小. 这个大小是包含了所有内容编码的, 比如, 对文本文件进行了gzip压缩的话, Content-Length首部指的就是压缩后的大小而不是原始大小.

Content-Length是如何工作的

Content-Length使用十进制的数字表示了消息的长度, 服务端/客户端通过它来得知后续要读取消息的长度.

image
image

如果这个长度不正确, 会发生如下情况:

Content-Length > 实际长度

如果Content-Length比实际的长度大, 服务端/客户端读取到消息结尾后, 会等待下一个字节, 自然会无响应直到超时.

image

同样地, 在响应消息中Content-Length超过实际长度也是一样的效果:

image
image

Content-Length < 实际长度

如果这个长度小于实际长度, 首次请求的消息会被截取, 比如参数为param=piaoruiqingContent-Length为10, 那么这次请求的消息会被截取为: param=piao, 如图所示:

image
image

但, 仅仅是如此吗, 当然不, 我们再来看看第二次请求会发生什么让人意外的事情, 如图:

image

连续的两次请求, 第一次消息被截断, 而第二次没有发生预期的截断, 而是服务端抛出了异常: Request method 'ruiqingPOST' not supported.刺不刺激 (ノ)゚Д゚( )

那 ruiqingPOST是个什么神仙方法??? 此时, 凭着多年开发(DEBUG)经验练就的敏感度, 我们大致可以猜出, 上一次请求被截取剩下的消息, 在这次请求出现了. 掏出wireshark来验证一下, 如图:

image

导致这种情况的原因就是开启了Connection:keep-alive, 如果使用Connection:close, 所产生的现象就是每一次的请求都被截断, 但不会产生解析混乱(如将上一次剩下的消息拼接到后续的请求消息中).

不确定Content-Length的值怎么办

Content-Length首部指示出报文中实体主体的字节大小. 但如在请求处理完成前无法获取消息长度, 我们就无法明确指定Content-Length, 此时应该使用Transfer-Encoding: chunked

什么是Transfer-Encoding: chunked

数据以一系列分块的形式进行发送. Content-Length 首部在这种情况下不被发送. 在每一个分块的开头需要添加当前分块的长度, 以十六进制的形式表示,后面紧跟着 \r\n , 之后是分块本身, 后面也是\r\n. 终止块是一个常规的分块, 不同之处在于其长度为0.

Transfer-Encoding: chunked是如何工作的

接下来我们用一个下载文件的例子, 来探讨Transfer-Encoding: chunked是如何工作的. 服务端代码如下:

image

使用postman发起请求, wireshark抓包查看, 如图:

image

在wireshark中可以很清晰地看到chunked的数据, 其结构大致是: 返回的消息被分为多个数据块, 每个数据块有两部分, 长度 + 数据, 这两部分都以CRLF(即\r\n)结尾. 而终止块是一个特殊的数据块, 其长度为0, 如图:

image

如此, 即完成了分块编码. 其主要应用于如下场景, 即要传输大量的数据, 但是在请求在没有被处理完之前响应的长度是无法获得的. 例如, 当需要用从数据库中查询获得的数据生成一个大的HTML表格、需要传输大量的图片等.

  • Content-Length如果存在且生效, 必须是正确的, 否则会发生异常.(大于实际值会超时, 小于实际值会截断并可能导致后续的数据解析混乱)
  • 如果报文中包含Transfer-Encoding: chunked首部, 那么Content-Length将被忽略.
  • from:https://blog.piaoruiqing.com
posted on   DoubleLi  阅读(1788)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2018-08-06 Ice框架简介及Vs2013安装Ice 3.7.0步骤及实例
2018-08-06 Zeroc Ice 3.6.1 生成 vs2015 c++ 版本库及相关配置
2018-08-06 vs 2017/2015/2013 如何定位C++内存泄漏
2018-08-06 【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题
2018-08-06 在VS2013平台下如何快速解决c++代码内存泄漏问题
2017-08-06 cmake使用示例与整理总结
2017-08-06 CMake使用总结
点击右上角即可分享
微信分享提示