Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

HTTP协议学习笔记

11
Aug
2013

HTTP协议学习笔记

By Alex
/ in Network
/ tags HTTP
0 Comments
基本知识
  1. HTTP是一种请求/应答模式(Request–Response pattern)的应用层协议
  2. HTTP基于TCP协议进行传输
URL与资源

URI是一类通用的资源标识符,由两个主要的子集URL和URN构成。 URL(统一资源定位符)用于表示浏览器寻找信息时所需的资源位置。

URL的语法

大多数URL方案(Scheme)的语法格式如下:

1
[scheme]://[user]:[password]@[host]:[port]/[path];]params]?[query]#[frag]

各部分说明如下:

组件  说明 
方案(scheme) 指定访问服务器以获取资源时要使用哪种协议
用户(user) 某些方案访问资源时需要的用户名
密码(password) 某些方案访问资源时需要的密码
主机(host) 资源宿主服务器的主机名或IP地址
端口(port) 资源宿主服务器正在监听的端口号,很多方案都有默认端口号
路径(path) 服务器上资源的本地名,由一个斜杠(/)将其与前面的URL组件分隔开来。路径组件的语法与服务器和方案有关
参数(params) 某些方案会用这个组件来指定输入参数。格式为名/值对;。URL中可以包含多个参数字段,每个参数字段尾部附加分号 
查询(query) 某些方案会用这个组件传递参数以激活应用程序。査询组件的内容没有通用格式。用字符?将其与URL的其它组件分隔开
片段(frag)  一小片或一部分资源的名字。该组件在客户端内部使用,不会传递给服务器,使用字符#与其它URL组件分隔

下面是一些合法URL的例子:

1
2
3
4
5
6
7
8
9
10
11
https://blog.gmem.cc
https://blog.gmem.cc:442
 
ftp://alex:pswd@ftp.gmem.cc/public/readme.txt
ftp://anonymous@ftp.gmem.cc/public/readme.txt
 
mailto:me@gmem.cc
 
jdbc:oracle:thin:@//dc.gmem.cc:1521/gmem
 
file://D:/Programs/Scripts/autoproxy.pac
相对URL

URL有两种方式:绝对的和相对的URL。相对URL是不完整的,要获取其指向的资源,必须找到其基础URL:

  1. 如果HTML文档包含 标签,那么使用该标签指定的URL
  2. 如果没有声明上述标签,该HTML文档本身所属的URL将用来分析基础URL
如果基础URL指定为 http://gmem.cc/codes/ 则相对URL ./index.html 对应绝对URL为: http://gmem.cc/codes/index.html 
如果基础URL指定为 http://gmem.cc/codes 则相对URL ./index.html 对应绝对URL为: http://gmem.cc/index.html 
 
注意点号.和双点号..,分别代表当前目录和上级目录。../..则代表上级目录的上级目录。
URL的字符编码

为安全的处理特殊字符,URL引入了转义语法,转义字符以百分号%开头,后面跟随两位十六进制的数字。常用特殊字符的编码如下:

字符 ASCII编码  示例 
~ 126(0x7E)  http://gmem.cc/HTTP%20faq.html 
空格 32(0x20)
% 37(0x25)

对于非ASCII字符的URL编码,标准规范没有规定如何处理,因此不同浏览器的实现有所不同,这导致服务器端难以正确的解码URL中包含的字符。对于这些字符,可移植性最好的方法是使用JavaScript将其转换为Unicode编码,函数escape/unescape、encodeURI/decodeURI用于完成Unicode编码处理:

 Unicode字符 Unicode编码 URL编码
绿 \u7EFF %u7EFF
HTTP报文
报文格式

HTTP报文由三个部分组成:

  1. 起始行(Start line):对报文进行简短的描述,分为请求行、响应行两种
  2. 首部(Header):包含若干报文属性。以一个空白行结尾
  3. 主体(Entity body):可选的数据主体部分

其中起始行、首部是逐行的ASCII文本,每行使用\r\n两个连续字符(CRLF)进行终止。主体部分则不同,可以是文本数据,也可以是二进制数据。

每个首部条目具有一定的格式: [名称]: [空白符][值][CRLF] ,如果首部的值过长,需要跨行的,那么非首行以至少一个空白字符开头。值中包含多个项目的,通常使用逗号分隔。不同首部字段可以按任意顺序排列。有些首部可以出现多次。

HTTP报文分为请求报文、响应报文两类。

请求报文的格式为:

1
2
3
4
5
[method] [request-URL] [version]
[headers]
 
[entity-body]
[last-content]

响应报文的格式为:

1
2
3
4
5
[version] [status] [reason-phrase]
[headers]
 
[entity-body]
[last-content]

上述格式中各组件的描述如下:

 组件 说明 
方法(method) 客户端希望服务器对资源执行的动作。参考下面的常用HTTP方法小节
请求URL(request-URL) 客户端请求的资源的完整URL
版本(version) 报文所使用的HTTP版本,格式为: HTTP/[major].[minor] 其中主、次版本号均为整数
状态码(status-code) 由3位数字组成,描述了请求过程中所发生的情况。每个状态码的第1位数字用于描述状态的一般类别
原因短语(reason-phrase) 数字状态码的可读版本
首部(header)

可以有零个或多个首部,每个首部都包含一个名字,后面跟着一个冒号(:),然后是一个可选的空格,接着是一个值,最后是一个CRLF。首部由一个空行 (CRLF)结束

有些HTTP版 本,比如HTTP/1.1,要求有效的请求或响应报文中必须包含特定的首部

实体主体部分(entity-body) 包含一个由任意数据组成的数据块(chunks of data)。该部分是可选的
尾部内容(last content) 实体部分的特殊内容,可以包含一些追加的头部(trailing headers)或者标注请求/响应的结束
常用HTTP方法

HTTP方法仅对请求报文有意义。并非所有Web服务器支持所有的方法,Web服务器也可以制定自己的扩展方法。

HTTP方法  说明  是否包含主体
GET 从服务器获取一份文档 否
HEAD 只从服务器获取文档的首部 是
POST 向服务器发送需要处理的数据 是
PUT 将请求的主体部分存储在服务器上 否
TRACE 对可能经过代理服务器传送到服务器上去的报文进行追踪 否
OPTIONS 决定可以在服务器上执行哪些方法 否
DELETE 从服务器上删除一份文档 否
状态码

方法是用来告诉服务器做什么事情的,状态码则用来告诉客户端,发生了什么事情。状态码的分类如下:

httpcode

常见的状态码如下表:

httpcodes

报文首部
首部分类
 首部类型 说明 
通用首部  请求、响应报文都可以出现的首部。提供了报文最基本的信息
请求首部  提供关于请求的更多信息 
响应首部 提供关于响应的更多信息
实体首部 与HTTP报文的载荷(Payload)部分有关,可以描述报文体的尺寸、内容或者描述资源本身
扩展首部 非标准化的首部
通用首部
名称  说明 
Connection 允许客户端/服务器指定关于请求/响应连接的选项。举例: Connection: Keep-Alive 
Keep-Alive 调节Keep-Alive的行为。timeout、max属性在响应首部中发送,分别表示服务器希望连接持续的时间、还能为多少个事务保持连接活动状态。举例: Keep-Alive: max=5, timeout=120 
Date 提供报文创建的日期、时间戳。举例: Date: Tue, 11 Jul 2000 18:23:51 GMT 
MIME-Version MIME类型的版本
Trailer 如果报文采用了分块传输编码(chunked transfer encoding)方式,可以用这个首部列出位于报文拖挂(trailer)部分的首部集合。举例: Trailer: Date 
Trasfer-Encoding 报文使用了何种编码方式进行传输。举例: Transfer-Encoding: chunked 
Upgrade 给出发送端想升级使用的新版本或协议。举例: Upgrade: HTTP/2.0 
Via 显示报文传输的中间节点(例如代理、网关)。举例: Via: HTTP/1.1 Proxy1, HTTP/1.1 Proxy2 
Cache-Control 用于随报文发出缓存指令。举例: Cache-Control: max-age=10 。时间以秒为单位,除了指定max-age,还可以指定:no-store、no-cache、must-revalidate等
Pragma 另一种发送指令的方式,但不限于缓存指令。应当使用Cache-Control代替之。举例: Pragma: no-cache 提示服务器应当返回一个刷新后的文档,即使服务器是代理并且已有缓存
请求首部
名称  说明 
信息性请求首部:提供了客户端、请求本身的一些信息
Client-IP 提供客户端机器的IP地址 
From  提供客户端的电子邮件地址。举例: From: me@gmem.cc 
Host 请求发送往的服务器的主机名和端口。举例: Host: blog.gmem.cc 
Referer 从中发起了当前请求的文档的URL。举例: Referer: www.google.com 
UA-Color 提供与客户端显示器的显示顔色有关的信息
UA-CPU 给出客户端CPU的类型或制造商
UA-Disp 提供与客户端显示器能力有关的信息
UA-OS 给出运行在客户端机器上的操作系统名称及版本
UA-Pixels 提供了客户端显示器的像素信息
User-Agent 将发起请求的应用程序名称告知服务器。举例: User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) 
Accept首部:将客户端的偏好、能力告知服务器,以便服务器生成定制化的信息
Accept  告诉服务器,客户端能够支持哪些媒体类型。举例: Accept: text/html, image/* 
Accept-Charset 告诉服务器,客户端能够支持哪些字符集 。举例: Accept-Charset: iso-8859-1 
Accept-Encoding 告诉服务器,客户端能够支持哪些编码方式。举例: Accept-Encoding: gzip, compress 
Accept-Language  告诉服务器,客户端能够支持哪些语言。举例: Accept-Language: en, fr 
TE 告诉服务器,客户端能够使用哪些扩展传输编码。举例: TE: trailers 
条件请求首部:要求服务器在进行响应之前,确保条件为真
Expect 允许客户端列出所要求的服务器行为。举例: Expect: 100-continue 
If-Match 如果实体标记与文档当前的实体标记相匹配,就获取这份文档。举例: If-Match: entity_tag001 
If-Modified-Since 除非在某个指定的日期之后资源被修改过,否则就限制这个请求(服务器应当返回304应答)。举例: If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT 
If-None-Match 如果提供的实体标记与当前文档的实体标记不相符,就获取文档。举例: If-None-Match: entity_tag001 
If-Range 允许对文档的某个范围进行条件请求。举例: If-Range: entity_tag001
If-Unmodified-Since 除非在某个指定日期之后资源没有被修改过,否则就限制这个请求。举例: If-Unmodified-Since: Tue, 11 Jul 2000 18:23:51 GMT 
Range 如果服务器支持范围请求,就请求资源的指定范围。举例: Range: bytes=100-599 
与安全相关的请求首部
Authorization 包含了客户端提供给服务器,以便对其自身进行认证的数据。举例: Authorization: [credentials] 
Cookie 客户端可以用它向服务器传送一个令牌(例如Tomcat的JSESSIONID)
Cookie2 用来说明请求端支持的Cookie版本
与代理相关的请求首部
Max-Forwards 在通往服务器的路径上,将请求转发给其他代理或网关的最大次数(与TRACE方法一同使用)。举例: Max-Forwards: 3 
Proxy-Authorization 与Authorization首部功能相同,伹这个首部是在与代理进行认证时使用的
Proxy-Connection 与Connection首部功能相同,但这个首部是在与代理立连接时使用的
响应首部
名称  说明 
信息性响应首部
Age 响应的年龄,即响应是何时创建的,如果是从代理缓存获取的响应,可能Age早于请求时间。举例: Age: 2147483648 
Public 服务器为其资源支持的请求方法列表 
Retry-After 如果资源不可用的话,在此日期或时间重试。举例: Retry-After: 60 
Server 服务器应用程序软件的名称和版本。举例: Server: Microsoft-IIS/5.0 
Title HTML文档的标题
Warning 比原因短语中E详细一些的警告报文
协商首部:HTTP1.1可以允许服务器与客户端对资源进行协商
Accept -Ranges 对此资源来说,服务器可接受的范围类型。举例: Accept-Ranges: none 
Vary  服务器査看的其他首部的列表,可能会使响应发生变化,也就是说,这是 一个首部列表,服务器会根据这些首部的内容挑选出最适合的资源版本发送给客户端
与安全相关的响应首部
Proxy-Authenticate 来自代理的对客户端的质询(challenges)列表。举例: Proxy-Authenticate: Basic realm-admin 
Set-Cookie 可以在客户端设置一个令牌,以便服务器对客户端进行标识。举例:
1
2
3
4
#该Cookie将发送给任何*.gmem.cc的站点
Set-cookie: JSESSIONID="2c85d5b9"; domain="gmem.cc"
#该Cookie将发送给任何*.gmem.cc下所有的/index/*页面
Set-cookie: JSESSIONID="2c85d5b9"; domain="gmem.cc"; path="/index/"
Set-Cookie2 与 Set-Cookie 类似,来自RFC 2965
WWW-Authenticate 来自服务器的对客户端的质询列表
实体首部
名称  说明 
Allow 列出可以对此实体执行的请求方法。举例: Allow: GET, HEAD 
Location 对于一个已经移动的资源,用于重定向请求者至另一个位置。举例: Location: http://gmem.cc/redirect.php 
内容相关的实体头部
Content-Base 解析主体(Body)中的相对URL时使用的基础URL     
Content-Encoding 主体的编码方式。举例: Content-Encoding: gzip, compress 
Content-Language 理解主体时最适宜使用的自然语言。举例: Content-Language: en 
Content-Length 主体的长度或尺寸。举例: Content-Length: 9990 。该首部很重要,如果连接出现故障,主体被截断,该首部可以用来判断内容是否完整
Content-Location 资源的实际位置。举例: Content-Location: http://gmem.cc/page.php 
Content-MD5 主体的MD5校验和。举例: Content-MD5: [md5-digest] 
Content-Range 在整个资源中此实体所处的字节范围。举例: Content-Range: 1001-2000/5000 最后的5000表示总长度
Content-Type 主体的内容类型。举例: Content-Type: text/html 
实体缓存相关头部
ETag 与该实体关联的实体标记(Entity tag),对于可以使用多种URL请求的资源,ETag可以用于确定实际被发送的资源是否为同一资源。举例: ETag: b38b9-17dd-367c5dcd 
Expires 到什么时间(一个绝对时间)为止,实体将过期,应当从其原始出处重新获取。举例: Expires: Tue, 11 Jul 2000 18:23:51 GMT 
Last-Modified 实体最后一次修改的时间。举例: Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 
底层连接
HTTP/HTTPS协议栈

http-stack

性能影响因素
  1. DNS查找:如果URI对应的主机名在本地DNS缓存中不存在,则需要通过DNS服务器查找,该过程可能消耗几百毫秒——几十秒
  2. TCP握手与连接建立:小的HTTP事物可能在TCP连接的建立上花费超过50%的时间
  3. 其它与TCP协议本身有关的性能因素
提升HTTP性能
  1. 并行连接,如果同时开启多个TCP连接,可能提升HTML页面的加载性能。浏览器通常启用了并行连接,一般几个
  2. 持久化连接:在一个HTTP事物结束后,TCP连接不会关闭,直到服务器或者客户端显式的关闭。持久化连接包括:
    1. HTTP/1.0+ keep-alive:实现该特性的客户端通过Connection: Keep-Alive首部请求一条持久化连接。如果服务器支持该请求,则其在响应报文里面也加上Connection: Keep-Alive,否则就表示不支持,客户端将在收到响应后关闭连接
    2. HTTP/1.1 persistent:默认激活,因此除非特别说明,HTTP/1.1的连接默认是持久的。要在事务结束后关闭连接,必须在报文中显式的添加 Connection: close 首部。客户端和服务器可以随时关闭空闲连接
  3. 管道化连接:HTTP/1.1允许在持久化连接可选的使用请求管道。在响应到达之前,即可将后续的多条请求放入管道,该机制在高延迟网络中,有利于减少环回时间。客户端不应当以管道化方式处理非幂等操作(例如POST),非幂等操作必须等待前一条的响应到达后再次发送
客户端身份识别与Cookie机制

以下几种方式可以用于HTTP的身份识别:

  1. 承载用户身份信息的HTTP首部:多种HTTP首部可以用于承载用户身份相关信息。例如From、User-Agent、Referer、Authorization、Cookie等
  2. 客户端IP地址跟踪。该方式的缺点:
    1. 只能用于识别机器,而不是用户
    2. 对于动态分配的IP地址,无法使用
    3. 对于位于NAT背后的客户端主机,无法使用
    4. 服务器看到的可能是代理的IP地址,而不是真实客户端
    5. IP欺骗(伪造):在因特网上很容易发生,因此IP身份验证一般只适用于基于信任的内部网络
  3. 用户登录,使用HTTP基本认证来识别用户:HTTP提供了一个原生的质询/响应(challenge/response)框架,服务器可以发出401响应和WWW-Authentication首部,浏览器将弹出登录框,用户输入身份信息后,通过Base64编码存放到Authorization首部,并重发先前的请求
  4. 胖URL,在URL中嵌入识别信息:为每个用户生成特点版本的URL
  5. Cookie,一种功能强大、高效的持久身份识别技术

 Cookie的相关知识可以参考文章:HTTP知识集锦

安全HTTP
HTTPS简介

HTTPS是最流行的HTTP安全形式,由网景首创,主流浏览器均支持。HTTPS方案的URL以“https”开头。

使用HTTPS时,所有数据在通过网络发送之前,都要经过加密。HTTPS在HTTP(应用层)下面提供一个传输级的安全层,该安全层通过SSL或者其继任者TLS实现,可以认为HTTPS就是在SSL之上传输的HTTP。SSL与TLS非常类似,以下不作区分。

大部分涉及安全处理的编码、解码工作由SSL库完成,HTTPS协议端点只需要将TCP调用转为SSL的I/O调用、再辅以一些配置性的调用即可。

客户端用证书对服务器进行验证的过程

通过HTTPS建立安全Web事务后,现代浏览器会自动获得服务器的数字证书,如果没有数字证书,安全连接就会失败,服务器证书包含很多字段,包括:

  1. Web站点的名称和主机名
  2. Web站点的公开密钥(公钥)
  3. 证书颁发结构的名称
  4. 来自证书颁发机构的、对上述公钥的签名

浏览器会对颁发机构进行检查,对于权威的颁发机构,其公钥一般已经被浏览器预装。浏览器可以通过此公钥对签名的有效性进行核实。如果浏览器对颁发机构一无所知,则通常会提示用户,询问其是否信任此颁发机构。

HTTPS技术细节

HTTPS将数据发送到TCP层之前,会通过SSL对数据进行加密。基于SSL的安全传输机制的建立过程如下:

  1. 客户端连接到服务器的HTTPS端口(默认443),建立TCP连接
  2. 客户端和服务器通过SSL握手,初始化SSL层
    1. 交换协议版本号
    2. 选择一个两端都知晓的密码
    3. 对两端的身份进行验证
    4. 生成临时会话密钥,用于通道加密
  3. 客户端将HTTP报文发送给SSL层,SSL层将其加密,然后传递给TCP层并通过网络发送出去
HTTP/2

HTTP/2 的目的是通过支持完整的请求与响应复用来减少延迟,通过有效压缩 HTTP 标头字段将协议开销降至最低,同时增加对请求优先级和服务器推送的支持。为达成这些目标,HTTP/2 还给我们带来了大量其他协议层面的辅助实现,例如新的流控制、错误处理和升级机制。

HTTP/2 没有改动 HTTP 的应用语义。HTTP 方法、状态代码、URI 和标头字段等核心概念一如往常。不过,HTTP/2 修改了数据格式化(分帧)以及在客户端与服务器间传输的方式。

各主流客户端对HTTP2的支持情况参考:https://caniuse.com/#feat=http2

二进制分帧层

HTTP/2 所有性能增强的核心在于新的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端与服务器之间传输:

http2-frame

 

这里所谓的“层”,指的是位于套接字接口与应用可见的高级 HTTP API 之间一个经过优化的新编码机制,HTTP 的语义不受影响,不同的是传输期间的编码方式变了。HTTP/2 将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码。

数据流、消息和帧

新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。 为了说明这个过程,我们需要了解 HTTP/2 的三个概念:

  1. 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息
  2. 消息:与逻辑请求或响应消息对应的完整的一系列帧
  3. 帧:HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流

注意:

  1. 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流
  2. 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息
  3. 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧
  4. 帧是最小的通信单位,承载着特定类型的数据,例如 HTTP 头、消息负载
  5. 来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装
帧

帧是HTTP/2最小通信单元,在一个TCP连接上,同一时刻最多有一个帧在发送。

帧报文的格式(单位bit):

1
2
3
4
5
6
7
8
9
+-----------------------------------------------+
|                 Length (24)                   |
+---------------+---------------+---------------+
|   Type (8)    |   Flags (8)   |
+-+-------------+---------------+-------------------------------+
|R|                 Stream Identifier (31)                      |
+=+=============================================================+
|                   Frame Payload (0...)                      ...
+---------------------------------------------------------------+

字段说明:

  1. Length:帧载荷部分的长度
  2. Type: 帧类型。0000 0000为DATA帧,0000 0001为HEADERS帧
  3. Flags:不同类型的帧分别设置,特殊标记位。例如HEADERS帧会设置END_HEADERS标记位来提示头传送完毕
  4. R:无用
  5. Stream Identifier:当前帧所属的流的标识符
  6. Frame Payload帧的载荷部分
流

HTTP/2支持多路复用,每一路就是一个流。流具有标识符,每个帧都指明它所属的流的标识符。

由于HTTP/2支持Server Push,也就是说服务器可以主动创建流。那么客户端和服务器的流ID如何防止冲突?协议规定,服务器使用偶数,客户端使用奇数。

流的状态转换示意图:

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
32
33
34
35
36
                                +--------+
                        send PP |        | recv PP
                       ,--------|  idle  |--------.
                      /         |        |         \
                     v          +--------+          v
              +----------+          |           +----------+
              |          |          | send H /  |          |
       ,------| reserved |          | recv H    | reserved |------.
       |      | (local)  |          |           | (remote) |      |
       |      +----------+          v           +----------+      |
       |          |             +--------+             |          |
       |          |     recv ES |        | send ES     |          |
       |   send H |     ,-------|  open  |-------.     | recv H   |
       |          |    /        |        |        \    |          |
       |          v   v         +--------+         v   v          |
       |      +----------+          |           +----------+      |
       |      |   half   |          |           |   half   |      |
       |      |  closed  |          | send R /  |  closed  |      |
       |      | (remote) |          | recv R    | (local)  |      |
       |      +----------+          |           +----------+      |
       |           |                |                 |           |
       |           | send ES /      |       recv ES / |           |
       |           | send R /       v        send R / |           |
       |           | recv R     +--------+   recv R   |           |
       | send R /  `----------->|        |<-----------'  send R / |
       | recv R                 | closed |               recv R   |
       `----------------------->|        |<----------------------'
                                +--------+
 
          send:   endpoint sends this frame
          recv:   endpoint receives this frame
 
          H:  HEADERS frame (with implied CONTINUATIONs)
          PP: PUSH_PROMISE frame (with implied CONTINUATIONs)
          ES: END_STREAM flag
          R:  RST_STREAM frame

其中:

  1. idle:流目前尚未启用
  2. open:流目前正在使用
  3. closed:流已经使用完成
  4. reserved(local):本地保留,即将要使用但是尚未使用
  5. reserved(remote):远端保留,即将要使用但是未使用
  6. half closed(local):本地半关闭,即将关闭但是尚未关闭
  7. half closed(remote):远端半关闭,即将关闭但是尚未关闭

收到或者发送HEADERS这种类型的帧会使流进入open状态,也就是说,HEADERS一定会建立一个新的流

发送PUSH_PROMISE的那一方会把流保存为reserved(local)的状态,当发送完HEADERS之后会变成half closed(remote)状态

帧类型
帧类型 说明
0x0 DATA 关联到帧的任意长度的帧,为了传递一个HTTP请求/应答,可能需要多个DATA帧
0x1 HEADERS 用于打开流,附带一些HTTP头片段,可以发送到idle、reserved(local)、open、half-closed(remote)类型的流
0x2 PRIORITY 指定发送者建议的、流的优先级
0x3 RST_STREAM 用于立即终止流
0x4 SETTINGS 携带影响端点通信方式的参数
0x5 PUSH_PROMISE 用于在准备发起流之前,通知对方。附带将要创建的流的ID以及一系列头数据
0x6 PING 用于度量RTT,测试空闲连接是否还在正常工作
0x7 GOAWAY

用于发起连接的shutdown,或者指示严重的错误状态

使用此帧,可以优雅的禁止建立新流,同时允许旧流正常完毕

0x8 WINDOW_UPDATE 用于实现流控,流控可以在窗口级别、整个连接级别进行
0x9 CONTINUATION 用于继续一系列的头部块片段。前置的帧必须是不设置END_HEADERS的HEADERS, PUSH_PROMISE, 或CONTINUATION 
0xa ALTSVC 允许源的资源在另外一个网络位置访问,可能用不同的协议访问
0xc ORIGIN 在指定的连接山,什么源(Origin)是可用的
消息结构

一个典型的HTTP报文包含请求/响应,组成如下:

  1. 零或多个HEADERS帧,一个HEADERS帧可能跟着0-N个CONTINUATION帧,以补充单个HEADERS容量不够的情况。大部分情况下一个HEADERS帧就包含了完整的报文头
  2. 0-N个DATA数据帧,包含了具体的消息载荷内容
  3. 一个HEADERS帧,后面跟随0-N个包含有报尾(Trailer-part)的CONTINUATION帧
服务器推送

HTTP/2服务器可以对一个客户端请求发送多个响应。换句话说,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端明确地请求。

所有服务器推送数据流都由 PUSH_PROMISE 帧发起,表明了服务器向客户端推送所述资源的意图,并且需要先于请求推送资源的响应数据传输。

在客户端接收到 PUSH_PROMISE 帧后,它可以根据自身情况(例如有缓存)选择拒绝数据流(通过 RST_STREAM 帧)。

协议协商

Google的SPDY协议包含名为NPN的TLS扩展,SPDY被HTTP/2取代后,NPN相应的成为ALPN(应用层协议协商)。

客户端在建立 TLS 连接的 Client Hello 握手中,通过 ALPN 扩展列出了自己支持的各种应用层协议,其中HTTP/2 协议名称是 h2。如果服务端支持 HTTP/2,在 Server Hello 中指定 ALPN 的结果为 h2 则协商完成,否则从客户端ALPN的列表中选择一个自己支持的协议。

← 2013年7月秦皇岛
Git学习笔记 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • AsyncHttpClient知识集锦
  • HTTP知识集锦
  • 基于Calico的CNI
  • 基于Broadway的HTML5视频监控
  • TCP/IP协议栈学习笔记

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • Bazel学习笔记 38 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2