HTTP

概念

  • 用于从WWW服务器传输超文本到本地浏览器的传送协议

  • 应用层协议,由请求和响应构成

  • 标准的客户端服务器(C/S)模型

  • 无状态

  • 在Internet中所有的传输都是通过TCP/IP进行的(HTTP协议通常承载于TCP协议之上,有时也承载于TLS/SSL协议层之上,即HTTPS

  • HTTP默认的端口号为80,HTTPS的端口号为443

特点

  • HTTP协议永远都是客户端发起请求,服务器回送响应
  • 支持客户端/服务器模式。支持基本认证和安全认证
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记
  • HTTP 0.9和1.0使用非持续连接:限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接
  • HTTP 1.1使用持续连接:不必为每个web对象创建一个新的连接,一个连接可以传送多个对象,采用这种方式可以节省传输时间
  • 无状态:HTTP协议是无状态协议(导致每次连接传送的数据量增大)

无状态协议

  • 协议的状态是指下一次传输可以“记住”这次传输信息的能力
  • HTTP是不会为了下一次连接而维护这次连接所传输的信息
  • 设计HTTP协议时规定Web服务器发送HTTP应答报文和文档时,不保存发出请求的Web浏览器进程的任何状态信息
  • 由于Web服务器不保存发送请求的Web浏览器进程的任何信息,因此HTTP协议属于无状态协议(Stateless Protocol)

无状态与Connection:keep-alive区别

  • HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)
  • 从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性
  • Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间

工作流程

  • 一次HTTP操作称为一个事务,其工作过程可分为四步:
  1. 首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP的工作开始
  2. 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容
  3. 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容
  4. 客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接(HTTP/1.0)
  • HTTP是基于传输层的TCP协议,而TCP是一个端到端的面向连接的协议。所谓的端到端可以理解为进程到进程之间的通信

头域

请求信息

  1. 三部分分别为:请求行、请求头(可多行)、空行、请求体
  2. 请求体前的空行为必需

请求方法

  • OPTIONS - 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送*的请求来测试服务器的功能性

  • HEAD - 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新

  • GET - 向特定的资源发出请求

  • POST - 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改

  • PUT - 向指定资源位置上传其最新内容

  • DELETE - 请求服务器删除Request-URI所标识的资源

  • TRACE - 回显服务器收到的请求,主要用于测试或诊断

  • CONNECT - HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器

  • PATCH - 用来将局部修改应用于某一资源,添加于规范RFC5789

  • 方法名称区分大小写

  • HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的

响应信息

  • 结构

  • 三部分分别为:状态行、响应头(可多行)、空行、响应信息(非必需)

HTTP常见请求头 & HTTP常见响应头

解决HTTP无状态的问题

  • 通过Cookies保存状态信息

  • 通过Session保存状态信息

    • 一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息

      当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存

    • 实现方式:

      1. 使用Cookie实现

        服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。
        当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID。这样服务器能够找到这个客户端对应的Session

      2. 使用URL回写实现

        1. 服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带会服务器
        2. Tomcat对Session的实现,是一开始同时使用Cookie和URL回写机制(优先使用Cookie,如果被禁用就是用URL回写)
  • TOKEN

缓存实现原理

  • WEB缓存(cache)位于Web服务器和客户端之间
  • 缓存会根据请求保存输出内容的副本(当下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访问请求,而不是向源服务器再次发送请求)

客户端缓存生效的常见流程

  1. 服务器收到请求时,返回的 200 OK 中回送该资源的Last-ModifiedETag(Entity Tags)头,客户端将该资源保存在cache中,并记录这两个属性。
  2. 客户端需要发送相同的请求时,会在请求中携带If-Modified-SinceIf-None-Match两个头。这两个头的值分别是响应中的Last-ModifiedETag值。
  3. 服务器通过这两个头判断本地资源未发生变化,客户端不需要重新下载,返回304响应

Web 缓存机制

HTTP/1.1中缓存的目的是为了在很多情况下减少发送请求,同时在许多情况下可以不需要发送完整响应。

  • 前者减少了网络回路的数量;HTTP利用一个“过期(expiration)”机制来为此目的
  • 后者减少了网络应用的带宽;HTTP用“验证(validation)”机制来为此目的

HTTP 定义了三种缓存机制:

  1. Freshness:允许一个回应消息可以在源服务器不被重新检查,并且可以由服务器和客户端来控制
    (Expires回应头给了一个文档不可用的时间。Cache-Control中的max-age标识指明了缓存的最长时间)
  2. Validation:用来检查一个缓存的回应是否仍然可用
    (如果一个回应有一个Last-Modified回应头,缓存能够使用If-Modified-Since来判断是否已改变,以便判断根据情况发送请求)
  3. Invalidation:在另一个请求通过缓存的时候,常常有一个副作用
    (如果一个URL关联到一个缓存回应,但是其后跟着POST、PUT和DELETE的请求的话,缓存就会过期)

HTTP应用

断点续传

  1. 将上传/下载的任务人为划分为几个部分
  2. 通过Header里的两个参数实现,Range(客户端发送请求)和Content-Range(服务器回复响应)
# 请求头:指定第一个字节的位置和最后一个字节的位置
Range:(unit=first byte pos)-[last byte pos]
# 响应头:当前接受的范围和文件总大小
Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]


# 示例
Range: bytes=0-499 			   表示第 0-499 字节范围的内容
Range: bytes=500-999 		   表示第 500-999 字节范围的内容
Range: bytes=-500 			   表示最后 500 字节的内容
Range: bytes=500- 			   表示从第 500 字节开始到文件结束部分的内容
Range: bytes=0-0,-1 		   表示第一个和最后一个字节
Range: bytes=500-600,601-999   同时指定几个范围

Content-Range: bytes 0-499/22400

# 响应完成后
# 不使用断点续传方式
HTTP/1.1 200 OK
# 使用断点续传方式
HTTP/1.1 206 Partial Content
  • 增强校验

    场景:URL对应的文件内容在服务器端发生变化

    1. Last-Modified

    2. Etag

    3. If-Range:判断实体是否发生改变,如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体

      # 格式
      If-Range: Etag | Last-Modified
      # If-Range 可以使用 Etag 或者 Last-Modified 返回的值。当没有 ETage 却有 Last-modified 时,可以把 Last-modified 作为 If-Range 字段的值
      If-Range: “627-4d648041f6b80”
      If-Range: Fri, 22 Feb 2013 03:45:02 GMT
      
      

      If-Range 必须与 Range 配套使用

      1. 如果请求报文中没有 Range,那么 If-Range 就会被忽略
      2. 如果服务器不支持 If-Range,那么 Range 也会被忽略
      • 如果请求报文中的 Etag 与服务器目标内容的 Etag 相等,即没有发生变化,那么应答报文的状态码为 206
      • 如果服务器目标内容发生了变化,那么应答报文的状态码为 200
    4. 用于校验的其他HTTP头信息:If-Match/If-None-Match、If-Modified-Since/If-Unmodified-Since

  • 工作原理

    Etag 由服务器端生成,客户端通过 If-Range 条件判断请求来验证资源是否修改。请求一个文件的流程如下:

    • 第一次请求:
      • 客户端发起 HTTP GET 请求一个文件
      • 服务器处理请求,返回文件内容以及相应的 Header,其中包括 Etag(例如:627-4d648041f6b80)(假设服务器支持 Etag 生成并已开启了 Etag)状态码为 200
    • 第二次请求(断点续传):
      • 客户端发起 HTTP GET 请求一个文件,同时发送 If-Range(该头的内容就是第一次请求时服务器返回的 Etag:627-4d648041f6b80)
      • 服务器判断接收到的 Etag 和计算出来的 Etag 是否匹配,如果匹配,那么响应的状态码为 206;否则,状态码为 200
  • 检测服务器是否支持断点续传

    • 使用CURL检测
    • 能够找到Content-Range,说明服务器支持断点续传
    • 有些服务器还会返回Accept-Ranges,输出结果Accept-Ranges: bytes,说明服务器支持按字节下载

多线程下载的原理

  • 下载工具开启多个发出HTTP请求的线程;
  • 每个http请求只请求资源文件的一部分:Content-Range: bytes 20000-40000/47000
  • 合并每个线程下载的文件

http代理

Nginx入门_yangcx的专栏-CSDN博客

虚拟主机

  • 把一台运行在互联网上的服务器划分成多个“虚拟”的服务器,每一个虚拟主机都具有独立的域名和完整的Internet服务器(支持WWW、FTP、E-mail等)功能。
  • 一台服务器上的不同虚拟主机是各自独立的,并由用户自行管理。
  • 一台服务器主机只能够支持一定数量的虚拟主机,当超过这个数量时,用户将会感到性能急剧下降

虚拟主机是用同一个WEB服务器,为不同域名网站提供服务的技术。Apache、Tomcat等均可通过配置实现这个功能

HTTP认证方式

HTTP请求报头: Authorization
HTTP响应报头: WWW-Authenticate
HTTP认证是基于质询/回应(challenge/response)的认证模式

基本认证

basic authentication(HTTP1.0提出的认证方法)

  • 基于用户名和口令的登录验证
  • username:passwdBASE64加密后放在请求头Authorization
  • 密码明文传输

认证步骤:

  1. 客户端访问一个受http基本认证保护的资源
  2. 服务器返回401,要求客户端提供用户名和密码进行认证
    (认证失败,响应头会加上WWW-Authenticate: Basic realm="请求域"
  3. 客户端将输入的用户名密码用Base64进行编码后,采用非加密的明文方式传送给服务器
    Authorization: Basic Base64(username:passwd)
  4. 服务器解析Authorization并认证;如果成功,返回相应的资源。失败,返回401,要求重新进行认证

摘要认证

digest authentication(HTTP1.1提出的基本认证的替代方法)

  • 可以看做是基本认证的增强版本,不包含密码的明文传递
  • 使用MD5加密是为了达成"不可逆"(如果密码太过简单,可通过字典或查表暴力破解)

步骤:

  1. 客户端请求一个需要认证的页面,但是不提供用户名和密码
  2. 服务器返回401响应,并提供认证域(realm),及一个随机生成的、只使用一次的密码随机数nonce
  3. 提示输入用户名&密码
  4. 添加认证头,重新发起请求

HTTPS传输协议原理

全称Hypertext Transfer Protocol over Secure Socket Layer,是HTTP的安全版。
HTTP下加入SSL层,HTTPS的安全基础是SSL

两种基本的加解密算法类型

  • 对称加密:密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES等
  • 非对称加密:密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSADSA

HTTPS通信过程

HTTPS通信的优点

  • 客户端产生的密钥只有客户端和服务器端能得到;
  • 加密的数据只有客户端和服务器端才能得到明文;
  • 客户端到服务端的通信是安全的

版本演进

HTTP/0.9

# 请求
GET /index.html

# 响应
<html>
  <body>Hello World</body>
</html>
  • 只有一个命令GET
  • 协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式
  • 服务器响应回复数据完毕,就关闭TCP连接

HTTP/1.0

# 请求
# 第一行是请求命令,必须在尾部添加协议版本(HTTP/1.0)
# 后面就是多行头信息,描述客户端的情况
GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

# 响应
# 格式:"头信息 + 一个空行(\r\n) + 数据"。其中,第一行是"协议版本 + 状态码(status code) + 状态描述"
HTTP/1.0 200 OK 
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>
  • 任何格式的内容都可以发送

  • 除了GET命令,还引入了POST命令和HEAD命令

  • HTTP请求和回应每次都必须包括头信息(HTTP header),用来描述一些元数据

  • 新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等

  • 回应格式:"头信息 + 一个空行(\r\n) + 数据"。第一行是"协议版本 + 状态码(status code) + 状态描述"

  • Content-Type 字段

    • 1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式
    • 总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔
    • 支持自定义类型
    • MIME type还可以在尾部使用分号,添加参数
    • MIME type不仅用在HTTP协议,还可以用在其他地方,比如HTML网页
  • Content-Encoding 字段

    • 服务器响应时说明数据的压缩方法
    • 客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法
  • 客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式

  • 缺点

    • 每个TCP连接只能发送一个请求(发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接)

    • TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)

      解决办法:

      • 有些浏览器在请求时,用了一个非标准的Connection字段
      Connection: keep-alive
      
      • 要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段(除非客户端或浏服务器主动关闭连接)
      • 但是这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法

HTTP/1.1

  • 持久连接(persistent connection)

    • 新增特性
    • TCP连接默认不关闭,可以被多个请求复用,也不用声明Connection: keep-alive
    • 客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接
    • 规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接
    • 目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接
  • 管道机制

    • 新增特性
    • 在同一个TCP连接里面,客户端可以同时发送多个请求(管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求)
  • Content-Length 字段

    一个TCP连接现在可以传送多个回应,必需要区分数据包是属于哪一个回应的。

    这就是Content-length字段的作用,声明本次回应的数据长度

    # 告诉浏览器,本次回应的长度是3495个字节,后面的字节属于下一个回应
    Content-Length: 3495
    

    1.0版中,Content-Length字段不是必需的(TCP连接关闭,标明数据包接收完成)

  • 分块传输编码

    • 使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度

    • 产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)【对于耗时操作来说,服务器要等到所有操作完成才能发送数据,效率不高】

    • 1.1版规定可以不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)

    • 请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成

      HTTP/1.1 200 OK
      Content-Type: text/plain
      Transfer-Encoding: chunked
      
      25
      This is the data in the first chunk
      
      1C
      and this is the second one
      
      3
      con
      
      8
      sequence
      
      0
      
    • 每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度

    • 最后是一个大小为0的块,就表示本次回应的数据发送完了

  • 1.1版还新增了许多动词方法:PUTPATCHHEADOPTIONSDELETE

  • 客户端请求的头信息新增了Host字段,用来指定服务器的域名(可以将请求发往同一台服务器上的不同网站)

  • 缺点

    • 一个TCP连接里面,所有的数据通信是按次序进行的(服务器只有处理完一个回应,才会进行下一个回应;可能会造成"队头堵塞"(Head-of-line blocking))
    • 解决方法:1. 减少请求数;2. 同时多开持久连接
    • 如果HTTP协议设计得更好一些,这些额外的工作是可以避免的

HTTP/2

  • 二进制协议
  • 多工
  • 数据流
  • 头信息压缩
  • 服务器推送

参考地址:

posted @ 2021-08-10 20:42  yangcxx  阅读(225)  评论(0)    收藏  举报