协议之HTTP


Ax HTTP

HTTP协议,作为我们日常上网必不可少的一部分,有必要系统性学习。

超文本传输协议Hypertext Transfer Protocol,HTTP)是应用程序级的用于分布式、协作、超媒体信息的协议系统。

版本:目前的规范定义称为“HTTP/1.1”的协议,该协议包含了比HTTP/1.0更严格的要求,更加可靠。

特点:支持C/S模式、简单快速、灵活、无连接(1.1之后支持可持续连接)、无状态。

阅读文献:RFC2616

Bx HTTP URL

URL我们都很熟悉了,就是浏览器输入在地址栏的内容。

URI(统一资源标识符)由URL(统一资源定位符)和URN(统一资源名)两个子集构成。

Format

URL的语法描述

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

scheme:方法描述了请求资源时用了什么协议,用“:”与url其它部分隔开;
user:用户名描述了访问是带的用户名;
password:密码描述了用户名后面可能跟的密码,用“:”跟用户名隔开;
host:主机描述了网站主机名或ip地址,如果前面有用户名和密码,用@分开;
post:服务器当前正在监听的端口,http默认为80,https默认为443;
path:路劲描述了资源在服务器上的位置,用‘/’跟前面部分隔开;
params:参数描述了请求需要附加的参数,用“;”与其他部分隔开;
query:查询是用来激活服务器程序去执行某些操作,比如查询数据库等,用“?”与其余部分隔开;
frag:片段只在客户端使用,不发送到服务器端;

URL Coding

URL编码:保证URL的一致性、安全性和完整性

https://enomothem.com/categories/操作系统/
https://enomothem.com/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/  # 编码后

关于URL的编码,最早由US-ASCII码编码,但是因为只能编译127个字符,后使用utf-8编码。查询字符串的编码,用的是操作系统的默认编码

编码机制:%两个表示字符的ASCII码的十六进制数

所以在URL中不赞成使用%这样的保留字符。

Cx HTTP Message

我们来看一下报文,报文由三个部分组成,起始行、首部、主体。

Message Types

HTTP消息由客户机到服务器的请求(Request)和服务器到客户机的响应(Respond)组成

Message Header

HTTP报头字段包括**通用报头(general-header),请求头(request-header),响应头(response-header),以及实体头(entity-header)**字段,遵循相同的通用格式。

Message Body

HTTP消息的消息体(如果有)用于携带与请求或响应相关联的实体体。 只有当应用了传输编码时,消息体才不同于实体体,如Transfer-Encoding报头字段所示。

message-body = entity-body
             | <entity-body encoded as per Transfer-Encoding>

Message Length

消息的传输长度是message-body在消息中出现时的长度; 也就是说,在应用了任何传输编码之后。 当消息体包含在消息中时,该message-body的传输长度由下列之一确定(按照优先级的顺序):


1.   任何“绝对不能”包含消息体的响应消息(例如1xx、204和304响应以及对HEAD请求的任何响应)总是由报头字段后的第一个空行终止,而不管消息中存在实体报头字段。

2.   如果存在一个Transfer-Encoding报头字段(章节14.41),并且有除“identity”以外的任何值,那么传输长度由“chunked”传输编码(章节3.6)定义,除非消息通过关闭连接而被终止。

3.   如果Content-Length报头字段(章节14.13)存在,它的OCTETs十进制值代表实体长度和传输长度。Content-Length报头字段不能被发送,如果这两个长度不同(例如,如果存在Transfer-Encoding报头字段)。如果接收到的消息同时带有Transfer-Encoding报头字段和Content-Length报头字段,则必须忽略后者。

4. 如果消息使用媒体类型“multipart/byteranges”,并且传输长度没有指定,那么这个自限制媒体类型定义了传输长度。除非发送方知道接收方可以使用这种媒体类型,否则不要使用;1.1客户端在请求中出现带有多个字节范围说明符的Range报头,意味着客户端可以解析多部分/字节范围响应。

   range报头可能由不理解multipart/byterange的1.0代理转发;在这种情况下,服务器必须使用本节第1、3或5项中定义的方法来划分消息。

5.   服务器关闭连接。(关闭连接不能用来指示请求主体的结束,因为这将使服务器不可能发回响应。)为了兼容HTTP/1.0应用程序,包含消息体的HTTP/1.1请求必须包含有效的Content-Length报头字段,除非服务器是HTTP/1.1兼容的。如果一个请求包含一个消息体,并且没有给出Content-Length,如果服务器不能确定消息的长度,则应该以400(错误的请求)响应,如果它希望坚持接收有效的Content-Length,则应该以411(所需的长度)响应。

所有接收实体的HTTP/1.1应用程序必须接受“分块”传输编码(章节3.6),从而允许在消息长度无法确定的情况下使用该机制
提前。

消息绝对不能同时包含Content-Length报头字段和非标识传输编码。如果消息确实包含非标识传输编码,则必须忽略Content-Length。

当在允许消息体的消息中给出Content-Length时,其字段值必须与消息体中字节数完全匹配。HTTP/1.1用户代理必须在接收到和检测到无效长度时通知用户。

General Header Fields

有一些报头字段对请求和响应消息具有普遍适用性,但不适用于正在传输的实体。 这些报头字段仅适用于正在传输的消息。

       general-header = Cache-Control            ; 用于随报文传送缓存指示
                      | Connection               ; 允许客户端和服务器指定与请求/响应连接有关的选项
                      | Date                     ; 提供了日期的时间标志,说明报文是什么时间创建的
                      | Pragma                   ; 另一种随报文传送指示的方式,但并不专用缓存
                      | Trailer                  ; 如果报文采用了分块传输编码方式,就可以用这个首部列出位于报文拖挂部分的首部集合
                      | Transfer-Encoding        ; 告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式
                      | Upgrade                  ; 给出了发送端可能想要“升级”使用的新版本或协议
                      | Via                      ; 显示了报文经过的中间节点(代理、网关)
                      | Warning                  ; 警告报文

Request

Request-Line以一个方法令牌开始,接着是Request-URI和协议版本,以CRLF结束。 元素之间用SP字符分隔。 不允许CR或LF,除非在最后的CRLF序列中。

Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

Request Header Fields

    // 请求的信息性首部

    首部                                描述

    Client-IP               提供了运行客户端的机器的IP地址
    From                    提供了客户端用户的E-mail地址
    Host                    给出了接收请求的服务器的主机名和端口号
    Referer                 提供了包含当前请求URL的文档的URL
    UA-Color                提供了与客户端显示器的显示颜色有关的信息
    UA-CPU                  给出了客户端CPU的类型或制造商
    UA-Disp                 提供了与客户端显示器(屏幕)能力有关的信息
    UA-OS                   给出了运行在客户端机器上的操作系统名称及版本
    UA-Pixels               提供了客户端显示器的像素信息
    User-Agent              将发起请求的应用程序名称告知服务器

    // Accept首部

    首部                                  描述

    Accept                  告诉服务器能够发送那些媒体类型
    Accept-Charset          告诉服务器能够给发送那些字符集
    Accept-Encoding         告诉服务器能够发送那些编码方式
    Accept-Language         告诉服务器能够发送那些语言
    TE                      告诉服务器可以使用那些扩展传输编码


    // 条件请求首部

    首部                                描述

    Expect                  允许客户端列出某请求所要求的服务器行为
    If-Match                如果实体标记与文档当前的实体标记相匹配,就获取这份文档
    If-Modified-Since       除非在某个指定的日期之后资源被修改过,否则就限制这个请求
    If-None-Match           如果提供的实体标记与当前文档的标记不相符,就获取文档
    If-Range                允许对文档的某个范围进行条件请求
    If-Unmodified-Since     除非在某个指定日期之后资源没有被修改过,否则就限制这个请求
    Range                   如果服务器支持范围请求,就请求资源的指定范围

    // 安全请求首部

    首部                                  描述

    Authorization           包含了客户端提供给服务器,以便对其自身进行认证的数据
    Cookie                  客户端用它向服务器传送一个令牌————它并不是真正的安全首部,但确实隐含了安全功能
    Cookie2                 用来说明请求端支持的cookie版本

    // 代理请求首部

    首部                                  描述

    Max-Forward             在通往源端服务器的路径上,将请求转发给其他代理或网关的最大次数————与TRACE方法一同使用
    Proxy-Authorization     与Authorization首部相同,但这个首部是在与代理进行认证时使用的
    Proxy-Connection        与Connection首部相同,但这个首部是在与代理建立连接时使用的

Request Method

能在服务器端有操作的就是非安全方法,比如delete、put、post,不在服务器端有操作的就是安全方法,比如get、head,当然了安全方法并非不能在服务器端有操作,这是开发者可以控制的!

       Method         = "OPTIONS"                ; HTTP1.1增加:请求服务器告知其支持什么功能
                      | "GET"                    ; 用于请求服务器端发送某个资源。
                      | "HEAD"                   ; 跟GET方法类似,区别就是不返回主体
                      | "POST"                   ; 用于向服务器端发送数据,传输实体主体。
                      | "PUT"                    ; HTTP1.1增加:用于向服务器端修改、插入数据
                      | "DELETE"                 ; HTTP1.1增加:向服务器删除某个指定的资源
                      | "TRACE"                  ; HTTP1.1增加:用于向服务器端请求报文在发送的过程中经过了什么修改,主要用于测试
                      | "CONNECT"                ; HTTP1.1增加:将服务器作为代理,让服务器代替用户去访问其他网页,之后将数据返回给用户。
                      | "LINK"                   ; HTTP1.1移除:建立和资源之间的联系。
                      | "UNLINK"                 ; HTTP1.1移除:断开连接关系。
                      | extension-method
       extension-method = token

Idempotent: 幂等性请求,无论执行多少次,结果都是一样的。多次提交不会导致重复的记录。例如setTrue()函数就是幂等函数。
幂等性分析

做笔记:幂等性在面试常考到的。

GET肯定是幂等的,这是一个只读的请求,所以不会对计算机的资源改变。
POST不是幂等的,POST往往是新创建一个资源,例如新注册一个用户,新发一个帖子,发两遍就可能就是两个帖子。
PUT是幂等的,它是全部更新。而PATCH是部分更新。

PUT vs POST

主要区别在于幂等性,POST是新建一个资源,PUT则是替代现有的资源。
通常我们会首先使用POST新建一个资源,然后用PUT去修改或PATCH去部分修改,然后DELETE删除或GET去获取它。

POST /resource
PUT/DELETE/GET/PATCH /resource/{id}

实际场景中,PUT也可用于创建,如不存在则创建,存在则更新。

GET vs POST

POST 和GET本质都是一样的。区别在于可见性、可收藏性 、可存储性、安全性、编码性、长度限制、是否可后退按钮/刷新。

一、功能不同

1、get是从服务器上获取数据。后退或刷新对页面无害。

2、post是向服务器传送数据。后退或刷新会询问用户是否提交数据。

二、过程不同

1、get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。所以可以被加入书签。GET 会将数据存在浏览器的历史中。

2、post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。不能被加入书签。POST不记录在浏览器中。

三、获取值不同

1、对于get方式,服务器端用Request.QueryString获取变量的值。

2、对于post方式,服务器端用Request.Form获取提交的数据。

四、传送数据量不同

1、get传送的数据量较小,不能大于2KB。

2、post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。

五、安全性不同

1、get安全性非常低。

2、post安全性较高。

六、编码不同

1、GET 编码格式只能用ASCII码

2、OST没有限制

HEAD

HEAD的响应头与GET相同,在下载一个大文件时,我们需要知道这个文件有多大,首先我们可以下载一个它的头部信息,然后决定是否下载,可以节约资源。如果使用GET则会直接下载该资源。

OPTIONS

在渗透测试中常用于查询支持哪些方法,用于文件上传的利用。可以使用Burp Suite或者Curl命令。在开发中,通常用于CORS中做一个先行探测。

curl -X OPTIONS https://enomothem.com -i

TRACE

实现了通向目标资源的路径的一个消息回环(Look back)测试,提供DEBUG机制。在渗透测试中可以利用此方法获取信息,不使用的情况下建议关闭。

Request-URI

Request-URI是一个统一资源标识符,标识要应用请求的资源。

       Request-URI    = "*" | absoluteURI | abs_path | authority

Request-URI的四个选项取决于请求的性质。 星号“*”表示请求不应用于特定的资源,而是应用于服务器本身,并且仅当所使用的方法不一定应用于资源时才允许。

The absoluteURI

       GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1

在HTTP版本中,所有HTTP/1.1服务器必须接受绝对uri

Request-URI最常见的形式是用来标识一个源服务器或网关上的资源。

       GET /pub/WWW/TheProject.html HTTP/1.1
       Host: www.w3.org

然后是请求的其余部分。 注意绝对路径不能是空的; 如果没有在原始URI中出现,则必须是给定为“/”(服务器根)。

Respond

在接收并解释请求消息后,服务器会作出响应,使用HTTP响应消息。

       Response      = Status-Line               ; 状态行
                       *(( general-header        ; 
                        | response-header        ; 
                        | entity-header ) CRLF)  ; 
                       CRLF
                       [ message-body ]          ; 消息体

Status-Line

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

Status Code and Reason Phrase

状态码和原因短语,状态码以数字形式表示当前事务处于什么状态,原因短句就是解释原因,方便阅读

      - 1xx: Informational - Request received, continuing process
                            \ 请求收到,继续处理
      - 2xx: Success - The action was successfully received, understood, and accepted
                      \ 成功地接收、解析和接受了该操作  
      - 3xx: Redirection - Further action must be taken in order to complete the request
                          \ 为了完成请求,必须采取进一步的行动  
      - 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
                           \ 请求包含错误的语法或无法实现  
      - 5xx: Server Error - The server failed to fulfill an apparently valid request
                           \ 服务器未能完成一个明显有效的请求  

Status-Code:

      Status-Code    =
            "100"  : Continue                                # 继续。客户端应继续其请求
          | "101"  : Switching Protocols                    # 切换协议。
          | "200"  : OK                                        # 请求成功。一般用于Get和Post请求
          | "201"  : Created                                # 已创建。成功请求并创建了新的资源
          | "202"  : Accepted                                # 已接受。已经接受请求,但未处理完成
          | "203"  : Non-Authoritative Information          # 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
          | "204"  : No Content                                # 无内容。服务器成功处理,但未返回内容。
          | "205"  : Reset Content                            # 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图
          | "206"  : Partial Content                        # 部分内容。服务器成功处理了部分GET请求
          | "300"  : Multiple Choices                        # 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表
          | "301"  : Moved Permanently                        # 永久移动。请求的资源已被永久的移动到新URI
          | "302"  : Found                                    # 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
          | "303"  : See Other                                # 查看其它地址。与301类似。使用GET和POST请求查看
          | "304"  : Not Modified                            # 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源
          | "305"  : Use Proxy                                # 使用代理。所请求的资源必须通过代理访问
          | "307"  : Temporary Redirect                     # 临时重定向。与302类似。使用GET请求重定向
          | "400"  : Bad Request                            # 客户端请求的语法错误,服务器无法理解
          | "401"  : Unauthorized                            # 请求要求用户的身份认证
          | "402"  : Payment Required                        # 保留,将来使用
          | "403"  : Forbidden                                # 服务器理解请求客户端的请求,但是拒绝执行此请求
          | "404"  : Not Found                                # 服务器无法根据客户端的请求找到资源(网页)。开发者可以个性化该页面
          | "405"  : Method Not Allowed                        # 客户端请求中的方法被禁止
          | "406"  : Not Acceptable                         # 服务器无法根据客户端请求的内容特性完成请求
          | "407"  : Proxy Authentication Required            # 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
          | "408"  : Request Time-out                        # 服务器等待客户端发送的请求时间过长,超时
          | "409"  : Conflict                                # 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
          | "410"  : Gone                                    # 客户端请求的资源已经不存在。而且没有任何已知的转发地址
          | "411"  : Length Required                        # 服务器无法处理客户端发送的不带Content-Length的请求信息
          | "412"  : Precondition Failed                     # 客户端请求信息的先决条件错误
          | "413"  : Request Entity Too Large                # 由于请求的实体过大,服务器无法处理,因此拒绝请求。
          | "414"  : Request-URI Too Large                    # 请求的URI过长(URI通常为网址),服务器无法处理
          | "415"  : Unsupported Media Type                    # 服务器无法处理请求附带的媒体格式
          | "416"  : Requested range not satisfiable         # 客户端请求的范围无效
          | "417"  : Expectation Failed                        # 服务器无法满足Expect的请求头信息
          | "500"  : Internal Server Error                    # 服务器内部错误,无法完成请求
          | "501"  : Not Implemented                        # 服务器不支持请求的功能,无法完成请求
          | "502"  : Bad Gateway                            # 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
          | "503"  : Service Unavailable                    # 由于超载或系统维护,服务器暂时的无法处理客户端的请求。
          | "504"  : Gateway Time-out                        # 充当网关或代理的服务器,未及时从远端服务器获取请求
          | "505"  : HTTP Version not supported                # 服务器不支持请求的HTTP协议的版本,无法完成处理
          | extension-code

      extension-code = 3DIGIT
      Reason-Phrase  = *<TEXT, excluding CR, LF>

Dx Entity

如果不受请求方法或响应状态码的限制,请求和响应消息可以传输实体。 实体由实体头字段和实体主体组成,尽管有些响应只包含实体头。

Entity Header Fields

       entity-header  = Allow                    ; 列出了可以对此实体执行的请求方法
                      | Content-Encoding         ; 对主体执行的任意编码方式
                      | Content-Language         ; 理解主体时最适宜使用的自然语言
                      | Content-Length           ; 主体的长度或者尺寸
                      | Content-Location         ; 资源实际所处的位置
                      | Content-MD5              ; 主体的MD5校验和
                      | Content-Range            ; 在整个资源中此实体表示的字节范围
                      | Content-Type             ; 这个主体的对象类型
                      | Expires                  ; 实体不再有效,要从原始的源端再次获取此实体的日期和时间
                      | Last-Modified            ; 这个实体最后一次被修改的日期和时间
                      | extension-header

       extension-header = message-header

Entity Body

与HTTP请求或响应一起发送的实体主体(如果有的话)采用实体头字段定义的格式和编码。

entity-body    = *OCTET

通过编码,确保信息的安全正确传递。

Type:当一个实体体包含在消息中时,该实体体的数据类型 body是通过头字段Content- type和Content-Encoding确定的。 这些定义了一个两层的有序编码模型:

  entity-body := Content-Encoding( Content-Type( data ) )

Entity Length:消息的实体长度是在应用任何传输编码之前消息体的长度。

Ex Connections

tcp/ip建立连接需要做的事情,tcp/ip所带来的时延,以及从http的角度出发,提升网络性能的一些方法,涉及到串行连接、并行连接、持久连接、管道连接等概念

TCP流程

让我们来复习一下TCP连接。和三次握手四次挥手。

我们以访问https://www.enomothem.com:80/path/index.html为例说明:

  1. 浏览器从地址栏中解析处域名(主机名),也就是拿到www.enomothem.com
  2. 浏览器根据得到的主机名查询出ip地址,比如算出ip为185.199.110.153,(中间可能经过查找host文件或去查询dns服务器)
  3. 浏览器解析出端口(http默认为80,https默认为443)
  4. 浏览器发起一条到185.199.110.153端口为443的链接,(重建需要经过几次确定相关参数的来回“握手”)
  5. 浏览器发起请求报文
  6. 服务器返回响应报文
  7. 浏览器关闭连接(其实浏览器和服务器都可以在不通知对方的情况关闭连接)

TCP流是分段的,由IP分组传输,也就是说最终http报文是以ip分组的形式在网络之间传输。一个ip分组包含的数据信息如下:

    1. ip分组首部(通常为20字节)
    2. tcp段首部 (通常为20字节)
    3. tcp数据块 (0个或多个字节,实际http报文数据就在这里) 

三次握手

四次挥手

TCP确定一个连接

TCP用四个信息来唯一确定一条连接:源ip地址、源端口号、目的ip地址、目的端口号。只要其中有一个不同,那么就不是同一条连接。在任意时刻计算机都可以有几条tcp连接在打开状态。

对TCP性能的考虑

首先相对建立tcp连接、发送http请求报文以及响应报文相比,http事务处理的时间相对短很多很多,此时延可不用讨论,除非你的服务器超负载了或正在处理复杂的运算。因此,http事务的时延往往由以下原因组成

  1. 首先客户端解析ip地址或者端口号需要时间,如果当前没有访问过相关资源,那么解析还需要查询dns服务器,此操作,造成的时延较多,可能花费数十秒。
  2. 建立tcp链接会有建立时延,通常2s左右,如果当前的http事务较多,那么会很快叠加上去。
  3. 传输、处理请求报文需要时间
  4. 回传响应报文需要时间
  5. 当然还有其他因素,比如硬件、网络负载,以及报文尺寸等!
  • 性能聚焦区域

这里简要说明一下,建立tcp链接这个过程可能存在的时延分析,包括:经典三次“握手”、tcp慢启动拥塞控制机制等!

  • 经典三次“握手”说的就是http事务在建立tcp连接是需要做的相关参数确认过程,大概如下:
  1. 客户端发送携带“SYN”标记的TCP段说明发起连接请求
  2. 服务端返回“SYN”和“ACK”的TCP段说明已接受
  3. 最后客户端发送确认信息以确认连接
  • tcp慢启动说明了,tcp连接会随着时间的增加进行自我调谐。这个主要目的防止突然的tcp连接增多导致网络瘫痪,所以它会慢慢的调整传输速度,这个机制就叫做TCP慢启动。

HTTP连接的处理

connection能承载三种字段值:

    HTTP首部字段名,列出了只与此有关的首部;

    任意标签值,用于描述此链接的非标准选项;

    值close,说明操作完成之后需关闭这条持久连接。

接收端在收到请求报文之后,对报文进行解析,并查看connection首部中列出的首部列表,并在转发出去之前,删除相关首部,这一行为称为:“对首部的保护”。

优化的方法

此种机制描述了http事务一个一个接着发起,不能同时下载更多的资源,使得界面上用户看不到东西,体验不够好。串行连接没有很好的利用tcp/ip连接的慢启动机制!

并行连接

通过多条TCP连接发起并发的HTTP连接

持久连接

重用TCP连接,以消除连接及关闭时延

管道化连接

通过共享的TCP连接发起并发的HTTP请求

并行连接

浏览同时发起过个http事务,因为是并行的,所以时延也并行的,这样总时延较小,页面呈现更快,体验较好。但也不是总是这样,因为如果在网络速度很慢的时候,多个连接会去竞争本来不多的带宽,那么就谈不上加快速度了。还有就是并行连接也是需要付出代价的,比如增加系统内训消耗、服务器负载,比如有一个100客户端同时对服务发起100tcp并行连接的话,那么服务器就得负责10000个处理请求,很快的你的服务器就会爆掉。当然了,并行连接确实能带来视觉上的速度提升,因为相比于串行连接慢慢地显示数据而并行一下子能全部显示完信息,视觉上并行连接会给人速度更快的感觉!

Persistent Connections

在持久连接之前,需要建立一个单独的TCP连接来获取每个URL,这增加了HTTP服务器的负载,并导致Internet上的拥塞。使用内联图像和其他相关数据通常要求客户机在很短的时间内对同一服务器发出多个请求。这些性能问题的分析和结果来自一个原型实现。人们也探索了替代方案,例如T/TCP。

如果对同ip、同端口的发起多个http事务连接,那么可以在前一个事务处理完成之后不要关闭tcp连接,以此来减小建立tcp、tcp慢启动所带来的时延。相关概念阅读RFC文档。

Pipelining
一个支持持久连接的客户端可以“流水线”它的请求(即,发送多个请求而不等待每个响应)。 服务器必须按照接收请求的顺序向这些请求发送响应。

在连接建立后立即假定存在持久连接和管道的客户端应该准备在第一次管道尝试失败时重试它们的连接。 如果一个客户端进行了这样的重试,在它知道连接是持久的之前,它绝对不能管道。 如果服务器在发送所有相应的响应之前关闭了连接,客户端也必须准备好重新发送请求。 客户端不应该使用非幂等方法或非幂等方法序列对请求进行管道传输。 否则,过早终止传输连接可能导致不确定的结果。 一个客户想要发送一个非幂等函数,request应该等待发送该请求,直到收到前一个请求的响应状态。

Fx HTTP Version Differences

1、http/0.9:

1991,原型版本,功能简陋,只有一个命令GET。GET /index.html,服务器只能回应HTML格式字符串,不能回应别的格式

2、http/1.0:

1996年5月,支持cache,MIME,method
每个TCP连接只能发送一个请求,发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接,引入了POST命令和HEAD命令头信息是 ASCII 码,后面数据可为任何格式。服务器回应时会告诉客户端,数据是什么格式,即Content-Type字段的作用。这些数据类型总称为MIME 多用途互联网邮件扩展,每个值包括一级类型和二级类型,预定义的类型,也可自定义类型, 常见Content-Type值:text/xml image/jpeg audio/mp3

3、http/1.1:

1997年1月,引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。对于同一个域名,大多数浏览器允许同时建立6个持久连接,引入了管道机制,即在同一个TCP连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率

新增方法:PUT、PATCH、OPTIONS、DELETE

HTTP/1.0和HTTP/1.1的区别:

(1)缓存处理:在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略,例如Entity tag,If-Unmodified-Since,If-Match,If-None-Match等更多可供选择的缓存头来控制缓存策略
(2)带宽优化及网络连接的使用:HTTP1.0中,存在一些浪费带宽的现象,例如:客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),方便了开发者自由的选择以便于充分利用带宽和连接
(3)错误通知的管理:在HTTP1.1中新增24个状态响应码,如409(Conflict)表示请求的资源与资源当前状态冲突;410(Gone)表示服务器上的某个资源被永久性的删除
(4)Host 头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)
(5)长连接:HTTP 1.1支持持久连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,弥补了HTTP1.0每次请求都要创建连接的缺点

4、SPDY协议:

SPDY:2009年谷歌研发,综合HTTPS和HTTP两者优点于一体的传输协议,主要特点:
(1)降低延迟。针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率
(2)请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,可以保证用户能第一时间看到网页内容
(3)header压缩。HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量
(4)基于HTTPS的加密协议传输。大大提高了传输数据的可靠性
(5)服务端推送(server push)。采用了SPDY的网页,例如网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了

5、HTTP/2协议:

http/2.0:2015年,HTTP2.0是SPDY的升级版
(1)头信息和数据体都是二进制,称为头信息帧和数据帧
(2)复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,且不用按顺序一一对应,避免了”队头堵塞”,此双向的实时通信称为多工(Multiplexing)
(3)引入头信息压缩机制(header compression),头信息使用gzip或compress压缩后再发送;客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,不发送同样字段,只发送索引号,提高速度
(4)HTTP/2 允许服务器未经请求,主动向客户端发送资源,即服务器推送(server push)

HTTP2.0和SPDY区别:

(1)HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
(2)HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

Gx References

[1] https://www.rfc-editor.org/rfc/rfc2616.txt

[2] https://github.com/woai30231/http

[3] https://www.cnblogs.com/augustone/articles/5170761.html

[4] https://blog.csdn.net/u013783095/article/details/80360149

[5] https://www.bilibili.com/video/BV1644y1k7Sg?spm_id_from=333.337.search-card.all.click

[6] https://blog.csdn.net/weixin_51867896/article/details/122932514

[7] https://baijiahao.baidu.com/s?id=1618114723935605183&wfr=spider&for=pc

[8] https://www.runoob.com/tags/html-httpmethods.html


文章作者: Enomothem
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Enomothem !
  目录