首先让我们从一个问题入手,当我们在浏览器中输入 http://www.baidu.com/ 访问百度的时候浏览器做了哪些事情。(这里以 Chrome 浏览器为例)
首先 Chrome 搜索自身的 DNS 缓存。(如果 DNS 缓存中找到百度的 IP 地址,就跳过了接下来查找 IP 地址步骤,直接访问该 IP 地址。)
搜索操作系统自身的 DNS 缓存。(浏览器没有找到缓存或者缓存已经失效)
读取硬盘中的 host 文件,里面记录着域名到 IP 地址的映射关系,Mac 电脑中位于 /etc/hosts。(如果前1.2步骤都没有找到)
浏览器向宽带运营商服务器或者域名服务器发起一个 DNS 解析请求,这里服务器有两种方式解析请求,这在稍后会讲到,之后浏览器获得了百度首页的 IP 地址。
拿到 IP 地址后,浏览器就向该 IP 所在的服务器建立 TCP 连接(即三次握手)。
连接建立起来之后,浏览器就可以向服务器发起 HTTP 请求了。(这里比如访问百度首页,就向服务器发起 HTTP 中的 GET 请求)
服务器接受到这个请求后,根据路径参数,经过后台一些处理之后,把处理后的结果返回给浏览器,如果是百度首页,就可以把完整的 HTML 页面代码返回给浏览器。
浏览器拿到了百度首页的完整 HTML 页面代码,内核和 JS 引擎就会解析和渲染这个页面,里面的 JS,CSS,图片等静态资源也通过一个个 HTTP 请求进行加载。
浏览器根据拿到的资源对页面进行渲染,最终把完整的页面呈现给用户。
如果浏览器没有后续的请求,那么就会跟服务器端发起 TCP 断开(即四次挥手)。
至此,整个访问过程就结束了,可见浏览器帮我们做了许多的事。这里只是简单的概括,实际情况远比这些复杂。
上面提到,服务器在接受 DNS 解析请求的时候一般会有两种处理方式,它们分别是递归名称解析和迭代名称解析。
递归名称解析:
用户在向根名称服务器发送请求如图中为访问网址为 ftp.cs.vu.nl 之后就不用管后续的请求了,该服务器知道 nl 服务器地址,并向其询问其子域 ftp.cs.vu 的地址,之后不断递归,最终返回给用户最终的 IP 地址。
迭代名称解析:
客户端向根名称服务器发送查询 ftp.cs.vu.nl 的地址时候,根名称服务器只知道 nl 地址,它并不管后续的请求,而是将该地址直接返回给用户,而用户在获得地址后继续向 nl 结点服务器询问 ftp.cs.vu 的地址。相当于后续查询需要自己用户来完成,最后拿到 ftp.cs.vu.nl 的 IP 地址。
HTTP 基本概念
HTTP,全称为 HyperText Transfer Protocol,即为超文本传输协议。是互联网应用最为广泛的一种网络协议,所有的 www 文件都必须遵守这个标准。
HTTP 特性:
HTTP 是无连接无状态的
HTTP 一般构建于 TCP/IP 协议之上,默认端口号是 80
HTTP 可以分为两个部分,即请求和响应。
HTTP 请求:
HTTP 定义了在与服务器交互的不同方式,最常用的方法有 4 种,分别是 GET,POST,PUT, DELETE。URL 全称为资源描述符,可以这么认为:一个 URL 地址,对应着一个网络上的资源,而 HTTP 中的 GET,POST,PUT,DELETE 就对应着对这个资源的查询,修改,增添,删除4个操作。
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
请求行(request line)、请求头部(header)、空行和请求数据四个部分组成
下图给出了请求报文的一般格式。
GET 请求报文实例:
状态行由请求方式,路径、协议等构成,各元素之间以空格分隔。对应到图中即为 GET、/books/?sex=man&name=Professional、 HTTP/1.1
请求头提供一些参数比如:Cookie,用户代理信息,主机名等等。(图中即从第二行到最后一行)
请求正文就放一些发送的数据,一般 GET 请求会将参数放在 URL 中,也就是在请求头中而请求正文一般为空,而 POST 请求将参数放在请求正文中。请求正文可以传一些 json 数据或者字符串等等。
GET 一般用于信息获取,比如刚才我们浏览百度首页,其使用的就是GET方法。
GET 请求一般不会产生副作用,它仅仅只是获取资源信息,就像数据库查询一样,不会修改、增加数据,不会影响资源的状态,并且对同一个 URL 的多次GET请求应该返回相同的结果。
POST 请求报文实例:
第一部分:请求行,第一行明了是post请求,以及http1.1版本。
第二部分:请求头部,第二行至第七行。
第三部分:空行,第八行的空行。
第四部分:请求数据,第九行。
Post被设计成用统一的方法实现下列功能:
1:对现有资源的解释;
2:向电子公告栏、新闻组、邮件列表或类似讨论组发信息;
3:提交数据块;
4:通过附加操作来扩展数据库 。
POST 请求表示可能会修改服务器上的资源。
GET 请求和 POST 请求的区别:
GET 和 POST 请求参数位置不同,从上面两个请求报文可以看出,GET 请求对应的参数放在 URL 中,而 POST 请求对应的参数放在 HTTP 请求主体中。(但是这只是一种约定,GET 请求中出现 Body 也是被允许的)
虽然 HTTP 协议的 RFC规范 并没有详细规定 URL 的最大字符长度限制,但实际上,在浏览器或者服务器中总会存在限制的,这就导致了 GET 请求中参数数量是有限的。
处于安全考虑,在一些涉及安全的请求比如:登录请求需要用 POST 提交表单,而GET 请求一般用来获取静态资源。
GET 请求可以被缓存,可以被收藏为书签,但 POST 可以被缓存,但不能被收藏为书签。
GET 请求的参数在 URL 中,因此绝不能用 GET 请求传输敏感数据。POST 请求数据则写在 HTTP 的请求头中,安全性略高于 GET 请求。
HTTP 头信息:
介绍完 HTTP 基本概念之后,下面介绍一些常见的 HTTP 请求头中字段的含义。
HTTP 请求头:
比如以请求百度首页为例:
Accept:指定客户端能够接收的内容类型,如常见的 text/html 等,最后返回的百度首页也是个 HTML 文件。
Accept-Encoding:表示浏览器有能力解码的编码类型。
gzip是 GNU zip 的缩写,它是一个 GNU 自由软件的文件压缩程序,也经常用来表示 gzip 这种文件格式。deflate是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。
Accept-Language:表示浏览器所支持的语言类型。(这里指中文、简体中文和英文)
Cache-Control:指定请求和响应遵循的缓存机制。(这里表示不需要缓存)
Connection:表示是否需要持久连接。(HTTP 1.1 默认进行持久连接即为 keep-alive, HTTP 1.0 则默认为 close)
Cookie:用于会话追踪,在本文后面就继续介绍。
Host:表示请求的服务器网址
User-Agent:用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户端使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
还有另外还有一些常见的请求头:
Content-Length: 请求的内容长度
Referer: 先前访问的网页的地址,当前请求网页紧随其后,说明你是先前是从哪个网址点击访问到该页面的,如果没有则不填。
Content-Type:内容的类型,GET 请求无该字段,POST 请求中常见的有 application/x-www-form-urlencoded 为普通的表单提交,还有文件上传为 multipart/form-data
上述列举的是比较常见的请求头及用法,如果想要全面了解更多参数,可以查阅 HTTP请求头大全 - 常用参考表对照表 - 脚本之家在线工具
参考资料
1.菜鸟博客
2.知乎