前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?

用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?

作者头像
草堂笺
发布于 2019-12-20 09:50:57
发布于 2019-12-20 09:50:57
8240
举报
文章被收录于专栏:代码如诗代码如诗

.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});

用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?

目录

由Content-Length导致的问题引发的一系列思考: 文章地址: https://cloud.tencent.com/developer/article/1557590 前段时间开发API网关, 使用postman调试时出现了超时的情况, 经排查确定是请求数据被处理后Content-Length与实际不一致导致的问题, 故有此文.

前言

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

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

什么是Content-Length

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

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

Content-Length是如何工作的

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

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

Content-Length > 实际长度

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

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

Content-Length < 实际长度

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

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

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

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

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

版权声明

代码语言:txt
AI代码解释
复制
 本文发布于[朴瑞卿的博客](https://blog.piaoruiqing.com/), 允许非商业用途转载, 但转载必须保留原作者[朴瑞卿](https://blog.piaoruiqing.com/) 及链接:[https://blog.piaoruiqing.com](https://blog.piaoruiqing.com/).
代码语言:txt
AI代码解释
复制
 如有授权方面的协商或合作, 请联系邮箱: [piaoruiqing@gmail.com](https://blog.piaoruiqing.com/mailto:piaoruiqing@gmail.com). 

不确定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是如何工作的. 服务端代码如下:

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

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

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

结语

  • Content-Length如果存在且生效, 必须是正确的, 否则会发生异常.(大于实际值会超时, 小于实际值会截断并可能导致后续的数据解析混乱)
  • 如果报文中包含Transfer-Encoding: chunked首部, 那么Content-Length将被忽略.

参考文献

© 2019, 朴瑞卿.

版权声明

代码语言:txt
AI代码解释
复制
 本文发布于[朴瑞卿的博客](https://blog.piaoruiqing.com/), 允许非商业用途转载, 但转载必须保留原作者[朴瑞卿](https://blog.piaoruiqing.com/) 及链接:[https://blog.piaoruiqing.com](https://blog.piaoruiqing.com/).      如有授权方面的协商或合作, 请联系邮箱: [piaoruiqing@gmail.com](https://blog.piaoruiqing.com/mailto:piaoruiqing@gmail.com).
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Qt简单屏幕截图(兼容Qt4/5)
Qt4使用 QPixmap::grabWindow接口获取指定屏幕; Qt5使用QScreen 的grabWindow接口获取指定屏幕; QApplication::desktop()获取根窗口; QUuid::createUuid()产生唯一ID; pixmap.save(name)保存截图到本地. main.cpp #include <QApplication> #include <QDesktopWidget> #include <QScreen> #include <QPixmap> #includ
Qt君
2019/07/15
2.5K0
Qt截图软件3-实现矩形区域截图
首先我们先获取到当前桌面的完整图片,然后将其放到一个全屏的透明窗口之中,之后,我们在窗口上进行绘制矩形操作,然后获取到绘制的区域即可。
kdyonly
2023/03/03
1.3K0
Qt开源作品31-屏幕截图控件
屏幕截图控件在我的很多项目中都有用到,尤其是嵌入式的系统上的软件,因为在嵌入式系统中,基本上系统都很精简,甚至连UI都没有,开机之后直接运行的就是Qt程序,很多时候需要对软件进行截图保存下来,用来编写文档和介绍,还有产品彩页之类的,毕竟在板子上直接运行的效果是最好的,还有一种办法是将系统编译成win的版本,用系统的截图来,但是嵌入式上很多代码其实很不方便在win上运行,甚至没法运行,而且还要外接很多接口来得到真正的运行效果,所以还是采用直接在板子上的Qt程序中直接集成截图的功能,需要的时候直接鼠标右键弹出来选择即可。
feiyangqingyun
2020/06/09
1K0
Qt开源作品31-屏幕截图控件
Qt快捷屏幕截图
介绍两种Qt屏幕截图的方法。 方法1 接口: QPixmap QScreen::grabWindow(WId window, int x = 0, int y = 0, int width = -1, int height = -1) 示例: QScreen *screen =
Qt君
2019/07/22
1.9K0
Qt官方示例-MDI(多文档界面)
  多文档界面例子主要使用了QMdiArea类实现。下面是介绍QMdiArea的使用。
Qt君
2023/03/17
1.9K0
Qt官方示例-MDI(多文档界面)
Qt截图软件2-实现截全屏功能
创建新项目,选择Qt Widgets Application桌面应用程序,选择之后,填写项目名称,根据默认选项走下一步到创建完成即可。 主界面设计,如图所示,可按照自己的想法进行可视化设计,增加Push Button,可以为按钮添加图标,首先我们可以增加资源文件,然后把图标全部放进资源文件中,如图所示,为按钮添加图标即可。 界面设计完成之后,我们可以对按钮添加功能代码,鼠标右键→转到槽→clicked(),这样我们就可以为按钮添加点击事件了。
kdyonly
2023/03/03
4740
Qt官方示例-数字时钟
DigitalClock继承于QLCDNumber,并实现一个槽函数showTime()用来定时更新时钟显示:
Qt君
2019/12/16
1.4K0
Qt官方示例-计算器
该示例显示了如何使用信号和槽来实现计算器小部件的功能,以及如何使用QGridLayout将子小部件放置在网格中。 通过绑定不同的按钮和不同的槽函数实现计算功能。 private slots:
Qt君
2019/11/24
5920
PyQt5 截取屏幕
本篇介绍如何用 PyQt5 截屏。 下面两行是PyQt 截屏的关键代码: screen= QtWidgets.QApplication.primaryScreen()#PyQt5 screen.gra
用户6021899
2019/08/14
4.5K0
Qt官方示例-缓和曲线
❝该示例演示如何使用「缓和曲线」来控制动画的速度。❞ 关于更多 在「QtCreator软件」可以找到: 或在 以下「Qt安装目录」找到: C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\widgets\animation\easing 「相关链接」 https://doc.qt.io/qt-5/qtwidgets-animation-easing-example.html
Qt君
2023/03/17
2310
Qt官方示例-缓和曲线
Qt开源作品23-颜色拾取器
在做很多项目的UI界面的时候,相信绝大部分人都有过抄袭别人的UI界面尤其是颜色的时候,毕竟十个程序员九个没有审美,或者说审美跟一坨屎一样,大家主要的精力以及擅长点都是在写功能实现具体功能上面,这个事情怎么说呢,这确实是程序员的主要职责,但是在大部分的小公司,UI也都是需要程序员自己去搞定的,自己想不出来怎么办,借鉴咯,不知道颜色值怎么办,用颜色拾取器点一下咯。
feiyangqingyun
2020/05/29
6990
Qt开源作品23-颜色拾取器
Qt官方示例-目录视图
声明model为用于读取本地文件系统的数据模型。model.setRootPath("")将当前文件夹设置为将从其model开始读取的文件夹。QTreeView对象tree以树结构的可视化文件系统。
Qt君
2020/02/13
9580
Qt官方示例-目录视图
Qt官方示例-样式表
  样式表示例显示了如何使用Qt样式表设置窗口小部件的样式。您可以通过选择"File" >"Edit Style"来打开样式编辑器,以选择现有样式表或设计自己的样式并加载它。
Qt君
2020/07/21
1.8K0
Qt官方示例-样式表
Qt官方示例-字体采样器
❝预览系列字体的例子。❞   建立字体树显示。 QFontDatabase database; fontTree->setColumnCount(1); fontTree->setHeaderLabels(QStringList() << tr("Font")); foreach (QString family, database.families()) { const QStringList styles = database.styles(family); if (styles.i
Qt君
2023/03/17
4370
Qt官方示例-字体采样器
Qt官方示例-系统托盘
❝该示例演示如何将带有菜单的图标和弹出消息添加到桌面环境的系统托盘。 ❞   总结该示例的一些使用方法如下: 0x01 创建并显示一个系统托盘 #include <QSystemTrayIcon> Q
Qt君
2020/05/25
2.7K0
Qt官方示例-系统托盘
Qt官方示例-共享内存
  构建示例,请运行make。要运行该示例,请运行两个实例。main()函数创建一个应用程序和我们示例的Dialog类的实例。显示对话框,然后将控制以标准方式传递给应用程序。
Qt君
2023/03/17
1.3K0
Qt官方示例-共享内存
Qt开源作品11-屏幕录制控件
在平时的写作过程中,经常需要将一些操作动作和效果图截图成gif格式,使得涵盖的信息更全面更生动,有时候可以将整个操作过程和运行效果录制成MP4,但是文件体积比较大,而且很多网站不便于上传,基本上都支持gif动图,一般一个5秒左右的gif,800*600分辨率,可以很好的控制在500KB内,这样就比较完美的支持各大网站上传动图。
feiyangqingyun
2020/05/16
1.1K0
Qt开源作品11-屏幕录制控件
Qt音视频开发49-通用截图截屏
采用了回调方式的视频通道,截图只需要对解析好的QImage对象直接保存即可,而对于句柄的形式,需要调用不同的处理策略,比如vlc需要用它自己提供的api接口函数libvlc_video_take_snapshot传入保存路径即可,mpv的内核执行screenshot-to-file命令传入路径参数即可,而ffmpeg就需要设置抓拍标志位,在实时采集解析那边,如果当前是截图标志位真,则需要改成QImage转换的机制发出图片,而不是yuv的数据opengl绘制,海康的sdk调用NET_DVR_CapturePicture函数即可。
feiyangqingyun
2020/11/24
1.7K0
Qt音视频开发49-通用截图截屏
QT软件开发: 截取全屏、指定位置、当前窗口保存图片
一、环境介绍 QT : 5.12.6 操作系统: win10 x64 编译器: MinGW32 二、示例代码 头文件 #include <QScreen> #include <QTimer> connect(&timer, SIGNAL(timeout()), this, SLOT(update())); timer.start(50); 2.1 截取全屏保存为图片 void Form::update() { static int cnt=0; QScreen *screen = QGuiA
DS小龙哥
2022/01/12
1.9K0
QT软件开发: 截取全屏、指定位置、当前窗口保存图片
Qt官方示例-菜单栏
本例子介绍如何在应用程序中使用菜单栏。 创建一个菜单栏 QMenu *menu = new QMenu(this); 添加一个菜单项目(Edit) editMenu = menuBar()->add
Qt君
2020/07/29
1.4K0
Qt官方示例-菜单栏
相关推荐
Qt简单屏幕截图(兼容Qt4/5)
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding ?
    • 前言
    • 什么是Content-Length
      • Content-Length是如何工作的
      • Content-Length > 实际长度
      • Content-Length < 实际长度
    • 不确定Content-Length的值怎么办
    • 什么是Transfer-Encoding: chunked
      • Transfer-Encoding: chunked是如何工作的
    • 结语
    • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档