本书是介绍怎么编写一个 Web 服务器,而 Web 服务器是基于 HTTP ( HyperText Transfer Protocol ) 协议实现的,所以要实现一个 Web 服务器就必须了解 HTTP 协议,本章主要介绍 HTTP 协议的 相关知识,让我们对 HTTP 协议有个理性的认识 。
我们日常生活中经常会使用浏览器访问 Web 站点,但是大家有思考过在这个过程中到底发生了什么吗?为什么我们在浏览器地址栏上面输入要访问的 URL 后就可以访问到 Web 页面呢?
当我们在浏览器地址栏上输入要访问的 URL 后,浏览器会分析出 URL 上面的域名,然后通过 DNS 服务器查询出域名映射的 IP 地址,浏览器根据查询到的 IP 地址与 Web 服务器进行通信,而通信的协议就是 HTTP 协议。
我们可以把这个过程类比成一个电话对话的过程。当我们要打电话给某个人,首先要知道对方的电话号码,然后进行拨号。打通电话后我们会进行对话,当然要对话肯定需要共同的语言,如果一个人说国语,而另一个人说英语,那肯定不能进行沟通的。在本例中,电话号码相当于上面的 IP 地址,而共同语言相当于 HTTP 协议。
我们通过一个简单的图来阐述这个过程:
图 1-1 浏览器访问 URL 过程
浏览器与 Web 服务器使用 HTTP 协议进行通信,那么什么是 HTTP 协议呢?接下来我们会详细介绍 HTTP 协议的 相关知识 。
HTTP 协议是构建在 TCP/IP 协议之上的,是 TCP/IP 协议的一个子集,所以要理解 HTTP 协议,有必要先了解下 TCP/IP 协议相关的知识。
由于 TCP/IP 协议族包含众多的协议,在这里我们无法一一讨论。接下来,我们仅介绍理解 HTTP 协议需要掌握的 TCP/IP 协议族的一些相关知识点。如果想深入理解 TCP/IP 协议,可以参考经典书籍《 TCP/IP 详解》。
TCP/IP 协议族分层
TCP/IP 协议族是由一个四层协议组成的系统,这四层分别为:应用层、传输层、网络层和数据链路层。如图 1-2 所示:
图 1-2 TCP/IP 协议族分层
分层的好处是把各个相对独立的功能解耦,层与层之间通过规定好的接口来通信。如果以后需要修改或者重写某一个层的实现,只要接口保持不变也不会影响到其他层的功能。接下来,我们将会介绍各个层的主要作用。
1) 应用层
应用层一般是我们编写的应用程序,其决定了向用户提供的应用服务。应用层可以通过系统调用与传输层进行通信。
处于应用层的协议非常多,比如: FTP ( File Transfer Protocol ,文件传输协议)、 DNS ( Domain Name System ,域名系统)和我们本章讨论的 HTTP ( HyperText Transfer Protocol ,超文本传输协议 )等。
2) 传输层
传输层通过系统调用向应用层提供处于网络连接中的两台计算机之间的数据传输功能。
在传输层有两个性质不同的协议: TCP ( Transmission Control Protocol ,传输控制协议)和 UDP ( User Data Protocol ,用户数据报协议)。
3) 网络层
网络层用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(传输路线)到达对方计算机,并把数据包传输给对方。
4) 链路层
链路层用来处理连接网络的硬件部分,包括控制操作系统、硬件设备驱动、 NIC ( Network Interface Card ,网络适配器)以及光纤等物理可见部分。硬件上的范畴均在链路层的作用范围之内。
上层协议数据是如何转变为下层协议数据的呢?这是通过封装( encapsulate )来实现的。应用程序数据在发送到物理网络之前,会沿着协议栈从上往下传递。每层协议都将在上层协议数据的基础上加上自己的头部信息(链路层还会加上尾部信息),以为实现该层功能提供必要的信息。如图 1-3 所示:
图 1-3 数据包封装
发送端发送数据时,数据会从上层传输到下层,且每经过一层都会被打上该层的头部信息。而接收端接收数据时,数据会从下层传输到上层,传输前会把下层的头部信息删除。过程如图 1-4 所示:
图 1-4 数据传输过程
由于下层协议的头部信息对上层协议是没有实际的用途,所以在下层协议传输数据给上层协议的时候会把该层的头部信息去掉,这个封装过程对于上层协议来说是完全透明的。这样做的好处是,应用层只需要关心应用服务的实现,而不用管底层的实现。
TCP 三次握手
从上面的介绍可知,传输层协议主要有两个: TCP 协议和 UDP 协议。 TCP 协议相对于 UDP 协议的特点是: TCP 协议提供面向连接、字节流和可靠的传输。
使用 TCP 协议进行通信的双方必须先建立连接,然后才能开始传输数据。 TCP 连接是全双工的,也就是说双方的数据读写可以通过一个连接进行。为了确保连接双方可靠性,在双方建立连接时, TCP 协议采用了三次握手( Three-way handshaking )策略。过程如图 1-5 :
图 1-5 TCP 三次握手
TCP 协议三次握手的描述如下:
第一次握手 :客户端发送带有 SYN 标志的连接请求报文段,然后进入 SYN_SEND 状态,等待服务端的确认。
第二次握手 :服务端接收到客户端的 SYN 报文段后,需要发送 ACK 信息对这个 SYN 报文段进行确认。同时,还要发送自己的 SYN 请求信息。服务端会将上述的信息放到一个报文段( SYN+ACK 报文段)中,一并发送给客户端,此时服务端将会进入 SYN_RECV 状态。
第三次握手 :客户端接收到服务端的 SYN+ACK 报文段后,会想服务端发送 ACK 确认报文段,这个报文段发送完毕后,客户端和服务端都进入 ESTABLISHED 状态,完成 TCP 三次握手。
当三次握手完成后, TCP 协议会为连接双方维持连接状态。为了保证数据传输成功,接收端在接收到数据包后必须发送 ACK 报文作为确认。如果在指定的时间内(这个时间称为重新发送超时时间),发送端没有接收到接收端的 ACK 报文,那么就会重发超时的数据。
前面介绍了与 HTTP 协议有着密切关系的 TCP/IP 协议,接下来介绍的 DNS 服务也是与 HTTP 协议有着密不可分的关系。
通常我们访问一个网站,使用的是主机名或者域名来进行访问的。因为相对于 IP 地址(一组纯数字),域名更容易让人记住。但 TCP/IP 协议使用的是 IP 地址进行访问的,所以必须有个机制或服务把域名转换成 IP 地址。 DNS 服务就是用来解决这个问题的,它提供域名到 IP 地址之间的解析服务。
图 1-6 展示了 DNS 服务把域名解析成 IP 地址的过程:
图 1-6 DNS 服务原理
DNS 服务是通过 DNS 协议进行通信的,而 DNS 协议跟 HTTP 协议一样也是应用层协议。由于我们的重点是 HTTP 协议,所以这里不打算对 DNS 协议进行详细的分析,我们只需要知道可以通过 DNS 服务把域名解析成 IP 地址即可。
1.1. 4 HTTP与 TCP/IP 、 DNS 的关系
到现在,我们介绍了与 HTTP 协议有密切关系的 TCP/IP 协议和 DNS 服务,接下来我们通过图 1-7 来整理一下 HTTP 协议与它们之间的关系:
图 1-7 HTTP 与 TCP/IP 、 DNS 的关系
从图 1-7 可以知道,当客户端访问 Web 站点时,首先会通过 DNS 服务查询到域名的 IP 地址。然后浏览器生成 HTTP 请求,并通过 TCP/IP 协议发送给 Web 服务器。 Web 服务器接收到请求后会根据请求生成响应内容,并通过 TCP/IP 协议返回给客户端。