在做网络编程(无论传统的Web开发,还是当前比较流行的的移动开发)的时候,我们用到最多的网络传输协议,可能就是HTTP协议了。作为开发者的我们可能更多的也只是去关注哪个第三方类库传输效率更高,哪个库使用最为方便,或者是哪个类库更为易于维护,但是,作为想要长期在该专业道路上行走的我们,仅仅学会使用这些类库的招式显然是不够的,我们还要了解其精髓,去分析源码,看看到底是如何实现的,那么问题来了,如果我们不懂HTTP协议的基础及核心内容,我们又该如何去分析那些源代码呢?无论哪个类库,最终的实现机制都是建立在对HTTP协议熟练掌握的基础上的。那么,让我们一起去彻底征服HTTP协议吧。

在了解之前,我先提几个问题,方便下面分析的时候,能够更好的去理解HTTP协议。

  • 1 如何理解HTTP协议的工作机制?

  • 2 如何建立一个网络请求,建立一个网络请求需要初始化哪些东西?

  • 3 如何将HTTP请求发送出去?

  • 4 如何接受到HTTP请求的响应信息?

为了更好的理解HTTP协议,我们先简单的了解一下TCP/IP协议族。通常我们所使用的网络都是在TCP/IP协议族的基础上运作的,HTTP也不例外。

一. TCP/IP协议族

客户端与服务器端进行相互通信,双方必须遵循相同的规则,比如:

  • 1 如何探测到通信目标

  • 2 由哪一边先发起通信

  • 3 使用哪种语言进行通信

  • 4 怎样结束通信

  • 5 不同的硬件、操作系统之间如何通信

而这一切都需要一种特定的规则来约束,我们称该规则为协议。

1. TCP/IP的分层管理

TCP/IP协议族最重要的一个特性就是分层。TCP/IP协议族按层次分别分为以下四层:应用层、传输层、网络层和数据链路层(OSI参考模型分为七层)。

  • 1 应用层
    作用:应用层决定了向用户提供应用服务时通信的活动。eg. DNS、FTP、HTTP。

  • 2 传输层
    作用:传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。eg. UDP、TCP。

  • 3 网络层
    作用:网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了通过怎样的路径到达对方计算机,并把数据包传给对方。

  • 4 链路层
    作用:用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、NIC及光纤等物理可见部分。

2. TCP/IP 通信传输流

3. 与HTTP关系密切的协议:IP、TCP和DNS

  • 1 负责传输的IP协议

    按层次分,IP位于网络层;
    IP协议的作用是把各种数据包传送给对方,而要确保传送到对方那里,则需要满足各类条件,其中两个重要的条件是IP地址和MAC地址;
    IP间的通信依赖MAC地址,采用ARP协议凭借MAC地址进行通信。

  • 2 确保可靠性的TCP协议

    按层次分,TCP位于传输层,提供可靠的字节流服务
    所谓字节流服务是指,为了方便传输,将大块数据分割成以报文段为单位的数据包进行管理。而可靠的传输服务是指,能够把数据准确可靠地传给对方。
    一言以蔽之,TCP协议为了更容易传送大数据才把数据分割,而且TCP协议能够确认数据是否送达到对方。

  • 3 负责域名解析的DNS服务

    DNS同HTTP协议一样位于应用层,提供域名到IP地址之间的解析服务。

4. 各种协议与HTTP协议的关系

HTTP在发送请求时,如果请求的地址写的是域名,则先访问DNS服务器获取目标服务器的IP地址,然后生成HTTP请求报文,发送给TCP层,按照TCP/IP通信传输流传输给目标服务器。

5. URI 和 URL

5.1 URI(统一资源标识符)

  • Uniform
    规定统一的格式可方便处理多种不同类型的资源,而不用根据上下文环境来识别资源指定的访问方式。

  • Resource
    资源的定义“可标识的人和东西”,资源不仅可以是单一的,也可以是多数的集合体。

  • Identifier
    表示可标识的对象。

综上:URI就是由某个协议方案表示的资源的定位标识符。

5.2URI 和 URL的关系

  • URI用字符串标识某一互联网资源,而URL表示资源的地址(互联网上所处的位置),可见是URI的子集。

  • URL是一种具体的URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,所以,是绝对的,而通常说的relative URL,则是针对另一个absolute URL,本质上还是绝对的。

二. HTTP协议

1. HTTP协议

  • HTTP是什么?
    HTTP(HyperText Transfer Protocol,超文本传输协议)是WWW (World Wide Web)实现数据通信的基石。
    它是一种应用层协议(OSI七层模型的最顶层),它基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

  • HTTP协议用于客户端和服务端之间的通信,通过请求和响应的交互达成通信(肯定是先从客户端开始建立通信的,服务器端在没有接收到任何请求之前不会发送响应)。

  • HTTP是不保存状态的协议,为了实现期望的保存状态的功能,引入了Cookie技术。

  • 告知服务器意图的HTTP方法
    GET:用来请求访问已被URI识别的资源,指定的资源经服务器解析后返回响应内容;
    POST:传输实体主体;
    PUT:传输文件,鉴于HTTP/1.1的PUT方法自身不带验证机制,任何人都可以上传文件,存在安全性问题,因此一般的网站不建议使用该方法。若配合Web应用程序的验证机制,或架构设计采用REST标准的同类Web网站,就可能会开放使用PUT方法。
    HEAD:获得报文首部,和GET方法一样,只是不返回报文主体部分,用于确认URI的有效性及资源更新的日期时间等。
    DELETE:删除文件,和PUT方法一样不带验证机制。
    OPTIONS:用来查询针对请求URI指定的资源支持的方法。
    TRACE:追踪路径,客户端通过TRACE方法可以查询发送出去的请求是怎样被加工修改/篡改的。这是因为,想要连接到源目标服务器可能会通过代理中转,TRACE方法就是用来确认连接过程中发生的一系列操作。
    CONNECT: 要求用隧道协议连接代理。CONNECT方法在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL和TLS协议把通信内容经网络隧道传输。

  • 持久连接节省通信量
    在HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接。
    假设这样的一个应用场景:使用浏览器请求一个包含多张图片的HTML页面时,在发送请求访问HTML页面资源的同时,也会请求该HTML里面包含的其他资源。因此,每次的请求都会造成无谓的TCP连接建立和断开,增加通信量的开销。

为了解决上述TCP连接的问题,HTTP想出了持久连接(HTTP keep-alive)的方法。持久连接的特点是:只要任意一端没有明确提出断开连接,则保持TCP连接状态。
管线化 持久连接使得多数请求以管线化方式发送成为可能。从前发送请求后需要等待并收到响应后,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求,这样就能够同时并行发送多个请求,而不需要一个接一个地等待响应了。

HTTP是无状态协议,不对之前发送的请求和响应的状态进行管理。不可否认无状态协议当然也有它自己的优点。由于不保存状态,自然可减少服务器的CPU及内存资源的消耗。保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了Cookie技术。Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端的状态。

2. HTTP报文

用于HTTP协议交互的信息被称为HTTP报文,客户端请求的报文称之为请求报文,服务端响应的报文称之为响应报文。HTTP报文大致可以分为报文首部报文主体两部分。二者由最初出现的空行(CR+LF)来划分。通常,并不一定要有报文主体。下面来看一下请求报文和响应报文的结构图:

编码提升传输速率

  • gzip(GNU zip)

  • compress (Unix系统的标准压缩)

  • deflate(zlib)

  • identity(不进行编码)

分割发送的分块传输编码

发送多种数据的多部分对象集合

获取部分内容的范围请求

在实现断点续传的功能的时候,就需要使用范围请求这个字段了。eg.Range: byte = 5001 - 10000

3. 返回结果的HTTP状态码

  • 1XX 表示服务器已经接收了客户端请求,客户端可继续发送请求

  • 2XX 请求正常处理完毕

  • 3XX 需要进行附加操作以完成请求

  • 4XX 表示客户端的请求有非法内容

  • 5XX 服务器处理请求出错
    下图为一些常用的状态码:

4. 与HTTP协作的Web服务器

用单台虚拟主机实现多个域名

一台Web服务器可搭建多个独立域名的Web网站,也可作为通信路径上的中转服务器提升传输效率。如果我们在一台服务器上托管了两个域名,当收到请求时就需要弄清楚究竟要访问哪个域名,因此必须在Host首部内完整指定主机名或域名的URI。

通信数据转发程序:代理、网关、隧道

HTTP通信时,除客户端和服务器以外,还有一些用于通信数据转发的 应用程序和服务器,例如代理、网关和隧道,它们可以配合服务器工作。这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并且能接收服务器返回的响应并转发给客户端。

  • 代理: 是一种有转发功能的应用程序
    代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器。代理不改变请求URI ,会直接转发给前方持有资源的目标服务器。
    使用代理服务器的理由:利用缓存技术减少网络带宽的流量。
    代理有多种使用方法,按两种基准分类。一类是 是否使用缓存 ,另一种是 是否会修改报文 。
    缓存代理:代理转发响应时,缓存代理会预先将资源的副本保存在代理服务器上,下次请求相同的资源时,则将之前缓存的资源作为响应返回。
    透明代理:转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理,否则称为非透明代理。

  • 网关: 是转发其他服务器通信数据的服务器
    利用网关可以由HTTP请求转化为其他协议通信。
    网关的工作机制和代理十分相似,而网关能使通信线路上的服务器提供非HTTP协议服务。

  • 隧道: 是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方通信连接的应用程序。
    隧道可按要求建立起一条与其他服务器的通信线路,届时使用SSL等加密手段进行通信。隧道的目的是确保确保能与服务器进行安全通信,隧道本身不会解析HTTP请求,请求保持原样中转给之后的服务器。

    保存资源的缓存

    利用缓存可减少对源服务器的访问,可以节省通信流量和通信时间。
    使用缓存的时候,要注意缓存的有效期限,确保我们发起请求获取的是最新的数据资源。

5. HTTP首部

我们首先来看一下请求报文和响应报文到底长什么模样,下面的示例代码是通过Firefox插件Firebug来抓去的百度页面首部信息:

  • 请求报文

12345678910111213141516171819
GET /his?wd=&from=pc_web&rf=3&hisdata=&json=1&p=3&sid=20740_20742_1424_18280_20417_17001_15840_11910_20744_20705&csor=0&cb=jQuery110206488567241711853_1469936513370&_=1469936513371 HTTP/1.1Host: www.baidu.comUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:47.0) Gecko/20100101 Firefox/47.0Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, *//*; q=0.01Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflate, brX-Requested-With: XMLHttpRequestReferer: https://www.baidu.com/Cookie: BAIDUID=DB24D5F4AB36694CF00C4877ADA56562:FG=1; BIDUPSID=DB24D5F4AB36694CF00C4877ADA56562; PSTM=1469936050; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm; BD_CK_SAM=1; H_PS_PSSID=20740_20742_1424_18280_20417_17001_15840_11910_20744_20705; BD_UPN=133252; H_PS_645EC=96a0XJobAseSCdbn9%2FviULLD7KreCHN4V4HzQtcGacKF8tGu13Nzd6j9PoB2SPPVj1d5; BD_HOME=0; __bsi=11860814506529643127_00_0_I_R_25_0303_C02F_N_I_I_0Connection: keep-alive

  • 响应报文

1234567891011121314151617
HTTP/1.1 200 OKServer: bfe/1.0.8.14Date: Sun, 31 Jul 2016 03:41:53 GMTContent-Type: baiduApp/json; v6.27.2.14; charset=UTF-8Content-Length: 95Connection: keep-aliveCache-Control: privateExpires: Sun, 31 Jul 2016 04:41:53 GMTSet-Cookie: __bsi=12018325985460509248_00_0_I_R_4_0303_C02F_N_I_I_0; expires=Sun, 31-Jul-16 03:41:58 GMT; domain=www.baidu.com; path=/

结合上面的HTTP报文结构图我们可以知道,两段代码的第一行分别对应请求行和响应行,下面则为首部字段。
通过首部字段的名字我们也可以知道,首部字段起着传递额外信息的重要作用,下面我们来简单了解一下HTTP首部字段:

6. 确保Web安全的HTTPS

通过上面的分析,我们了解到HTTP具有相当优秀和方便的一面,然而,HTTP并非只有好的一面,事物皆具两面性,主要存在以下几点不足:

  • 通信使用明文(不加密),内容可能会被窃听

  • 不验证通信方的身份,因此有可能遭遇伪装

  • 无法证明报文的完整性,所以有可能已遭篡改

HTTP+加密+认证+完整性保护=HTTPS
HTTPS并非是应用层的一种新协议。只是HTTP通信接口部分用SSL和TSL协议代替而已,通常,HTTP直接和TCP通信,当使用SSL时,则演变成先和SSL通信,再由SSL和TCP通信了。简言之,所谓HTTPS其实就是身披SSL协议这层外壳的HTTP。
当采用SSL后,HTTP就拥有了HTTPS的加密、证书和完整性保护这些功能。而且SSL协议是独立于HTTP的协议,所以不光是HTTP协议,其他运行在应用层的SMTP和Telnet等协议均可配合SSL协议使用。可以说SSL是当今世界上应用最为广泛的网络安全技术。

在讲解SSL之前我们需要首先了解一下加密方法,加密分为对称加密非对称加密。HTTPS协议则是采用的两者混合的实现方式,为什么要结合两种的实现方式呢?这是因为它们都各自存在自己的优缺点。对于对称加密来说,密钥的传输交换是不安全的,但是效率比较高,而对于非对称加密,是不用担心传输的密钥安全性的问题的,因为我们传递的是公开密钥,任何人都可以获得,但是缺点是效率比较低。对于公钥私钥、数字签名,这个哥们已经总结的相当好了,可以参考一下这篇文章

7. 确认访问用户身份的认证

何为认证?简单来说就是证明你是你自己!核对的信息通常有密码、动态令牌、数字证书、生物认证、IC卡等信息。
HTTP/1.1使用的认证方式如下:

  • BASIC认证(基本认证)

  • DIGEST认证(摘要认证)

  • SSL客户端认证

  • FormBase认证(基于表单认证)

8. 基于HTTP的功能追加协议

待续…
下面将会整体做个总结,完整的说明HTTP的工作机制。

三. 后记

本文是在阅读《图解HTTP》一书的基础上并同时参考一些优秀文章之后进行总结的,不仅整体认识了HTTP,也方便下次复习的时候,能够用更短的时间去理解这些虽然基础但是却很重要的知识。

四:参考资料

http://www.cnblogs.com/jingmoxukong/p/5115055.html
http://www.cnblogs.com/gaojing/archive/2012/02/04/2413626.html
http://network.chinabyte.com/401/13238901.shtml