理解 HTTP
HTTP 简介
-
什么是 HTTP?
超文本传输协议(Hyper Text Transfer Protocol)。
-
HTTP 是做什么的?
规范了浏览器和服务器交互的数据格式。
-
HTTP 的特点?
① 简单快捷: 客户向服务器请求服务时, 只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
② 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
③ 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
④ 无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。 1.1版本之后支持可持续性连接。
地址
URI
统一资源标识符(Uniform Resource Identifier)。
Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的。
-
URI一般由三部组成:
① 访问资源的命名机制;
② 存放资源的主机名;
③ 资源自身的名称,由路径表示,着重强调于资源。
URL
统一资源定位符(Uniform Resource Location),URL是URI概念的一种实现方式
。
URL是Internet上描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。
-
URL一般由三部组成:
① 协议(或称为服务方式);
② 存有该资源的主机IP地址(有时也包括端口号);
③ 主机资源的具体地址。如目录和文件名等。
示例:
例子:http://www.test.com:8080/test/index.html?id=521&page=1#str
组成 | 含义 | 例子 | 是否必填 |
---|---|---|---|
协议部分 | 在Internet中可以使用多种协议,如http,https,ftp等。 在"http"后面的 :// 为分隔符。 | http | 必填 |
域名部分 | 一个URL中,也可以使用IP地址作为域名使用。 | www.test.com | 必填 |
端口部分 | 跟在域名后面的是端口。 域名和端口之间使用 : 作为分隔符。 | 8080 | 端口不是一个URL必须的部分。 如果省略端口部分,将采用默认端口。 |
虚拟目录部分 | 从域名后的第一个 / 开始到最后一个 / 为止,是虚拟目录部分。 | /test/ | 非必填 |
文件名部分 | 从域名后的最后一个 / 开始到 ? 为止,是文件名部分。如果没有 ? ,则是从域名后的最后一个 / 开始到 # 为止,是文件部分。 如果没有 ? 和 # ,那么从域名后的最后一个 / 开始到结束,都是文件名部分。 | index.html | 文件名部分也不是一个URL必须的部分。 如果省略该部分,则使用默认的文件名。 |
参数部分 | 从 ? 开始到 # 为止之间的部分为参数部分,又称搜索部分、查询部分。 | id=521&page=1 | 非必填。 参数可以允许有多个参数,参数与参数之间用 & 作为分隔符。 |
锚部分 | 从 # 开始到最后,都是锚部分。 | str | 锚部分也不是一个URL必须的部分。 |
HTTP 请求过程
1. 域名解析
首先浏览器会解析域名(准确的叫法应该是主机名)得到对应的IP地址。
-
怎么解析到对应的IP地址?
① 浏览器会首先搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存),看自身的缓存中是否有该域名对应的条目,而且没有过期,如果有且没有过期则解析到此结束;
② 如果浏览器自身的缓存里面没有找到对应的条目,那么浏览器会搜索操作系统自身的DNS缓存,如果找到且没有过期则停止搜索解析到此结束;
③ 如果在Windows系统的DNS缓存也没有找到,那么尝试读取hosts文件(位于C:\Windows\System32\drivers\etc),看看这里面有没有该域名对应的IP地址,如果有则解析成功;
④ 如果在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(一般是电信运营商提供的,也可以使用像Google提供的DNS服务器)发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址),运营商的DNS服务器首先查找自身的缓存,找到对应的条目,且没有过期,则解析成功。如果没有找到对应的条目,则有运营商的DNS代我们的浏览器发起迭代DNS解析请求,它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),然后进一步请求;
正常情况下通过这四步基本就能解析域名获得IP了。
2.发起TCP3次握手
拿到域名对应的IP地址之后,User-Agent(一般是指浏览器)会以一个随机端口(1024 < 端口 < 65535)向服务器的WEB程序的80端口发起TCP的连接请求。这个连接请求(原始的http请求经过TCP/IP4层模型的层层封包)到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。
-
为什么HTTP协议要基于TCP来实现?
目前在Internet中所有的传输都是通过TCP/IP进行的,HTTP协议作为TCP/IP模型中应用层的协议也不例外,TCP是一个端到端的可靠的面向连接的协议,所以HTTP基于传输层TCP协议不用担心数据的传输的各种问题。
3. 建立TCP连接后发起HTTP请求
TCP3次握手之后,浏览器发起了http的请求。HTTP请求报文格式见下文的HTTP 消息结构。
4.服务器端响应http请求,浏览器得到html代码
服务器端WEB程序接收到http请求以后,就开始处理该请求,处理之后就返回给浏览器html文件。需要知道常见状态码,见下文。
5. 浏览器解析html代码,并请求html代码中的资源
浏览器拿到html文件后,就开始解析其中的html代码,遇到js/css/image等静态资源时,就向服务器端去请求下载(会使用多线程下载,每个浏览器的线程数不一样),这个时候就用上keep-alive特性了,建立一次HTTP连接,可以请求多个资源,下载资源的顺序就是按照代码里的顺序,但是由于每个资源大小不一样,而浏览器又多线程请求请求资源,所以请求成功显示的顺序并不一定是代码里面的顺序。
浏览器在请求静态资源时(在未过期的情况下),向服务器端发起一个http请求(询问自从上一次修改时间到现在有没有对资源进行修改),如果服务器端返回304状态码(告诉浏览器服务器端没有修改),那么浏览器会直接读取本地的该资源的缓存文件。
6. 浏览器对页面进行渲染呈现给用户
浏览器利用自己内部的工作机制,把请求到的静态资源和html代码进行渲染,渲染之后呈现给用户。
HTTP 消息结构
- 客户端请求消息:
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)
、请求头部(header)
、空行
和请求数据
四个部分组成,下图给出了请求报文的一般格式。
-
服务器响应消息:
HTTP响应也由四个部分组成,分别是:
状态行、消息报头、空行和响应正文
。状态行: 协议/版本号 状态码 状态码解释。
HTTP 请求方法
HTTP1.0定义了三种请求方法: GET,POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS,PUT,DELETE,TRACE 和 CONNECT 方法。
方法 | 说明 |
---|---|
GET | 请求指定的页面信息,并返回实体主体。一般用于获取/查询资源信息。 |
POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 |
HEAD | 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头。 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
DELETE | 请求服务器删除指定的页面。 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 |
OPTIONS | 允许客户端查看服务器的性能。 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
HTTP 状态码
当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型。
分类 | 说明 |
---|---|
1** | 信息性状态码,服务器收到请求,需要请求者继续执行操作 |
2** | 成功状态码 ,操作被成功接收并处理 |
3** | 重定向状态码,需要进一步的操作以完成请求 |
4** | 客户端错误状态码 ,请求包含语法错误或无法完成请求 |
5** | 服务器端错误状态码 ,服务器在处理请求的过程中发生了错误 |
常见的HTTP状态码:
状态码 | 说明 |
---|---|
200 | OK,请求成功,一般用于GET与POST请求 |
204 | No content,表示请求成功,但响应报文不含实体的主体部分 |
206 | Partial Content,进行范围请求 |
状态码 | 说明 |
---|---|
301 | moved permanently,永久性重定向,资源(网页等)被永久转移到其它URL |
302 | found,临时重定向,显式重定向,Location响应首部的值为新的URL |
303 | see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源 |
304 | not modified,未修改,比如本地缓存的资源文件和服务器上比较时,发现并没有修改 服务器返回一个304状态码,告诉浏览器,你不用请求该资源,直接使用本地的资源即可 |
307 | temporary redirect,临时重定向,和302含义相同 |
状态码 | 说明 |
---|---|
400 | bad request,请求报文存在语法错误。常见有ie中文参数乱码问题 |
401 | unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息 |
403 | forbidden,表示对请求资源的访问被服务器拒绝 |
404 | not found,表示在服务器上没有找到请求的资源 |
状态码 | 说明 |
---|---|
500 | internal sever error,服务器内部错误,无法完成请求 |
502 | Bad Gateway,前面代理服务器联系不到后端的服务器时出现 |
503 | service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求 |
504 | Gateway Timeout,这个是代理能联系到后端的服务器,但是后端的服务器在规定的时间内没有给代理服务器响应 |
HTTP 头部参数
参数 | 说明 |
---|---|
Connection | Close:告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了。 Keep-Alive:告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求。 |
User-Agent | 浏览器表明自己的身份 |
Content-Type | WEB 服务器告诉浏览器自己响应的对象的类型。 |
Cache-Control | 指定请求和响应遵循的缓存机制。 |
HTTP 响应头信息
参数 | 说明 |
---|---|
Allow | 服务器支持哪些请求方法(如GET、POST等)。 |
Content-Encoding | 文档的编码(Encode)方法。 |
Content-Length | 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。 |
Content-Type | 表示后面的文档属于什么MIME类型。 |
Date | 当前的GMT时间。 可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 |
Expires | 应该在什么时候认为文档已经过期,从而不再缓存它。 |
Last-Modified | 文档的最后改动时间。 |
Location | 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 |
Refresh | 表示浏览器应该在多少时间之后刷新文档,以秒计。 |
Server | 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 |
Set-Cookie | 设置和页面关联的Cookie。 |
WWW-Authenticate | 客户应该在Authorization头中提供什么类型的授权信息? |