HTTP详解

HTTP协议是“看不着、摸不着”的。因为在Java语言中,有太多的HTTP相关的库,如:HTTPClient、HTTPUrlConnection、Spring的RestTemplete等。因此在某种程度上从事Java相关的开发人员很难需要去深扒HTTP协议,而基本上都属于会用就好的状态。

编写本文的思路正如下面的文章目录。

目录

  • 一、HTTP简介
  • 二、什么是协议
    • 2.1 协议的定义
  • 三、Wireshark网络抓包工具
  • 四、HTTP协议
    • 4.1 前置知识
    • 4.2 请求协议结构
      • 4.2.1 描述
      • 4.2.2 抓包查看
    • 4.3 响应协议结构
      • 4.3.1 描述
      • 4.3.2 抓包查看
    • 4.4 分包传输
      • 4.4.1 结构图
      • 4.4.2 优点
      • 4.4.3 缺点
      • 4.4.4 抓包查看
    • 4.5 KeepAlive
      • 4.5.1 Tomcat对KeepAlive的支持
      • 4.5.2 TCP协议与HTTP协议中的KeepAlive区别
      • 4.5.3 如何复用长连接
      • 4.5.4 如何关闭长链接
      • 4.5.5 疑问待解决
      • 4.5.6 4.4 分包传输
  • 五、HTTP协议如何解决TCP的粘包与拆包

一、HTTP简介

HTTP中文名称是超文本传输协议(英文:HyperText Transfer Protocol),HTTP是基于 TCP/IP 协议之上的应用层协议,HTTP是万维网数据通信的基础。

因此,在HTTP建立之前,需要先等客户端与服务端建立TCP连接。

二、什么是协议

在了解具体的HTTP协议之前,最好还是先了解什么叫协议,这对之后的学习其它协议肯定会有帮助。

2.1 协议的定义

协议,网络协议的简称,网络协议是通信计算机双方必须共同遵从的一组约定。如怎么样建立连接、怎么样互相识别等。只有遵守这个约定,计算机之间才能相互通信交流。它的三要素是:语法、语义、时序。

为了使数据在网络上从源到达目的,网路通信的参与方必须遵循相同的规则,这套规则称为协议(protocol),它最终体现在网络上传输的数据包的格式。

协议往往分为几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。

备注:以上文字来源于百度百科

三、Wireshark网络抓包工具

Wireshark是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。

在学习HTTP协议的过程中,因为HTTP协议的是看不见摸不着的,这给学习带来一定的难度。因此有必要用Wireshark抓包工具抓取一个HTTP协议下来观察。

Wireshark官网地址:https://wireshark.en.softonic.com/
先看一下Wireshark的界面:

1.Wireshark1.png

显而易见:Wireshark抓包界面中分为顶部的菜单栏、过滤栏、上、中、下五个部分;

  • 过滤栏:用于写一些过滤条件,避免被抓的包太多,导致眼花缭乱不方便观察包
  • 上:请求列表,包含TCP、HTTP等等协议包
  • 中:一共有5个Item。从上到下分别为:物理层、数据链路层、网络层、传输层、应用层。有时候还会多一个Item,多的Item只是Wireshark将应用层中携带的数据解析出来展示而已,网络包中实际没有。因此这一区域的数据,Wireshark主要是用来展示更加人性化、经过加工后的数据。
  • 下:十六进制数据,是真正网络包中的数据;

四、HTTP协议

4.1 前置知识

在HTTP协议中,有很多的符号如:\n\r等,而也正是因为这些符号对HTTP协议解决拆包、粘包提供了基础

标识 ASCII 描述 字符
CR 13 回车 \n
LF 10 换行 \r
SP 32 空格
COLON 58 冒号 :

4.2 请求协议结构

4.2.1 描述

HTTP请求体中包含三个部分:① 请求行、② 请求头(Header)、③ 请求正文(Body)

0.HTTP协议Request透视图.png

概括为文字如下:

  • 请求行:

    包含三个部分:Method、URL、协议/版本,而这之前用空格隔开,在请求行的最后添加CRLF

  • 请求头:

    包含若干个键值对(格式为:key:value),在每个键值对之间都用CRLF隔开,在整个请求头的最后再加上一个CRLF;也就是说最后一个键值对的最后会有两个CRLF。

  • 请求正文:

    请求正文中主要是POST Method提交的数据,数据的格式可以有很多种,具体什么格式实在请求头中由Content-Type定义。在不考虑分包传输的情况下,请求正文中数据的字节数由Content-Length指定。

4.2.2 抓包查看

2.Wireshark2.png

4.3 响应协议结构

4.3.1 描述

HTTP响应体中包含三个部分:① 状态行、② 响应头(Header)、③ 响应正文(Body)

3.HTTP协议Response透视图.png

概括为文字如下:

  • 响应行:

    包含三个部分:协议/版本、响应状态码、状态码描述符,而这之前用空格隔开,在请求行的最后添加CRLF

  • 响应头:

    不说了,响应头格式同Request中的请求头格式

  • 响应正文:

    不说了,响应正文同Request中的请求正文

4.3.2 抓包查看

4.Wireshark4.png

看到这里,有的小伙伴可能会提出问题:

问:在上图中[响应头]与[响应正文]之间是什么数据呢?

答:这些数据是Wireshark为了辅助展示出的一些指标数据。实际上,在网络包中并没有这些数据,这里对比一下最下面的方块,看一下网络包中真正的数据。

问:在网络分层中,Hypertext Transfer Protocol已经是网络模型中的应用层了,那为什么上图的抓包中,最下面还有一层:Line-base text data:text/plain(1 lines)

答:这个问题的答案其实和上一个问题的答案一致,这只是Wireshark为了展示的更加人性化,将数据抽离在了该层展示低而已,注意看最下面的红色框框,在Header结束之后就是两个CRLF,紧接着就是数据(hello world!)了。

4.4 分包传输

在HTTP协议中,除了将数据放在一个包中一次性发出,还可以通过分包方式将一个大批数据分在多个数据包中进行传输。需要注意的是,分包传输使用的也是同一个Socket连接。
在Header中通过Transfer-Encoding: chunked进行指定,该KV与Content-Length只能同时出现一个。
需要注意的是:在HTTP1.0版本协议中不支持分包。在HTTP1.1之后开始支持分包。

4.4.1 结构图

5.chunked.png

4.4.2 优点

  • 当响应数据体量大时,避免浏览器出现忙等导致页面出现长时间的空白
  • 当要发送的数据长度很难计算时,为了保证吞吐量,可以先将一部分数据通过一个子包先发出去

4.4.3 缺点

  • 协议比较复杂

4.4.4 抓包查看

6.Wireshark6.png

4.5 KeepAlive

HTTP协议如果不做特殊处理都是一种短连接,即为一次会话建立TCP/IP之后,客户端与服务端基于TCP/IP的连接之上通过HTTP协议完成会话后,连接也会被服务端断开。下一次的HTTP请求,还是需要为这个请求进行三次握手创建TCP连接,用完之后还需要四次挥手断开TCP连接,这大大减少了传输效率。

而KeepAlive的产生就是为了弥补上述的不足。

HTTP1.0版本中需要在Header中加入Connection: keep-alive来指定会话完毕之后不立即断开连接,而是有一定的复用时间。HTTP1.1版本中,默认开启该配置:Connection: keep-alive

4.5.1 Tomcat对KeepAlive的支持

  • KeepAliveTimeout

    意义在于当请求结束之后默认要等待该值的时长,以达到复用的效果。

    在Tomcat9中,该参数值默认等于ConnectionTimeout的时长,而ConnectionTimeout在server.xml中默认是20000ms。ConnectionTimeout的含义在于:当连接建立起之后,可以忍受多久的时间客户端没有发数据过来。

    看一段Tomcat9的源码:

    <attribute name="keepAliveTimeout" required="false">
      <p>The number of milliseconds this <strong>Connector</strong> will wait
      for another HTTP request before closing the connection. The default value
      is to use the value that has been set for the
      <strong>connectionTimeout</strong> attribute.
      Use a value of -1 to indicate no (i.e. infinite) timeout.</p>
    </attribute>
    

    但是需要注意,该值最好别设置的太久,当大流量打入之后可能会导致资源始终无法释放。

    这里有一篇线上问题的复盘博客,可以参考一下:

    http://www.voycn.com/article/tomcat-connectiontimeout-lijie

  • MaxKeepAliveRequests

    Tomcat某个时刻最大能维护多少的长链接,这个值在Tomcat9版本中默认为100。

    看一段Tomcat9的源码:

    <attribute name="maxKeepAliveRequests" required="false">
      <p>The maximum number of HTTP requests which can be pipelined until
      the connection is closed by the server. Setting this attribute to 1 will
      disable HTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and
      pipelining. Setting this to -1 will allow an unlimited amount of
      pipelined or keep-alive HTTP requests.
      If not specified, this attribute is set to 100.</p>
    </attribute>
    

4.5.2 TCP协议与HTTP协议中的KeepAlive区别

需要注意的是:TCP协议中也有KeepAlive参数,但是与HTTP的KeepAlive还是有区别的;

  • TCP-KeepAlive

    TCP的KeepAlive是为了连接保活,该机制有三个重要的参数:

    tcp_keepalive_intvl:保活探测消息的发送频率

    tcp_keepalive_probes:需要发送X次的探测消息但依然无效,则认为连接断开

    tcp_keepalive_time:最后一次数据交换到TCP第一次发送探针消息的间隔时间

  • HTTP-Keep-Alive

    HTTP发出响应之后不要断开连接,连接需要保持一段时间,以达到复用的效果。

4.5.3 如何复用长连接

首先需要了解的是,复用到底复用的是什么,看了上面的介绍,短连接中的每次请求都需要先进行TCP的连接导致TCP链路无法复用,因此这里的复用其实是针对TCP链路的复用。

可以配合连接池,如HttpClient就对长连接具有管理的功能,注意这里的管理肯定是针对长连接了,短连接压根就无法复用。

4.5.4 如何关闭长链接

当TCP连接需要关闭时,只需要在Header头中添加Connection: close即可。

4.5.5 疑问待解决

Tomcat9版本中默认KeepTimeout为20s,我也查看了一下SpringBoot对于Tomcat的配置,发现SpringBoot没有对Tomcat参数做调整,至少KeepTimeout用的就是Tomcat默认值。

那么在这样的情况下,KeepTimeout最终应该为20s才对,但是在抓包过程中却发现其值为60s.

抓包如下:


7.Wireshark7.jpg

4.5.6 从JVM层面判断连接是否复用

TODO

五、HTTP协议如何解决TCP的粘包与拆包

TCP协议,数据传输都是stream式的,数据之间是没有流边界的,在这样情况下自然就会出现粘包与拆包的问题。那么基于TCP之上的HTTP协议当然也会面临这样的问题,那它是如何解决的呢?

了解了HTTP协议的结构之后,解决粘包拆包的问题就迎刃而解了。

HTTP的请求与响应,对于请求行、请求头、响应行、响应头而言,都可以通过CRLF与空格作为流的边界进行读取。

对于请求正文与响应正文而言,他们的字节长度在Header中的Content-Length中定义,假若,Header中没有Content-Length属性,取而代之的是Transfer-Encoding: chunked,那么就读取每一个chunk的size,继而再读取size个byte,知道读取到last-chunk的size为0。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • 何为http: 无状态的超文本传输协议(HTTP,HyperText Transfer Protocol)是...
    每天都是幸运的一天阅读 733评论 0 6
  • HTTP网络请求 对于android开发来说,http是网络开发中最为重要、使用频率最高的手段。 HTTP请求原理...
    幻灭一只狼阅读 6,739评论 0 11
  • 一、http协议的定义 HTTP是超文本传输协议的缩写。是互联网上使用最为广泛的一种网络协议,适用于www服务器传...
    小黑测试员阅读 615评论 0 0
  • 本文使用青花瓷软件和Wireshark进行抓包分析 Wireshark下载地址 点这里 Wireshark的使用:...
    AKyS佐毅阅读 2,076评论 0 20
  • HTTP协议,即超文本传输协议(HyperText Transfer Protocol),是基于TCP协议的应用层...
    renyjenny阅读 300评论 0 0