HTTP
1. HTTP 协议本质
HTTP
协议是浏览器与服务器之间的数据传送协议。作为应用层协议,HTTP
是基于TCP/IP
协议来传递数据的(HTML
文件、图片、查询结果等),HTTP
协议不涉及数据包(Packet
)传输,主要规定了客户端和服务器之间的通信格式。
下面通过一个例子来告诉你HTTP
的本质是什么。
假如浏览器需要从远程HTTP
服务器获取一个HTML
文本,在这个过程中,浏览器实际上要做两件事情。
- 与服务器建立
Socket
连接。 - 生成请求数据并通过
Socket
发送出去。
第一步比较容易理解,浏览器从地址栏获取用户输入的网址和端口,去连接远端的服务器,这样就能通信了。
我们重点来看第二步,这个请求数据到底长什么样呢?都请求些什么内容呢?或者换句话说,浏览器需要告诉服务端什么信息呢?
首先最基本的是,你要让服务端知道你的意图,你是想获取内容还是提交内容;其次你需要告诉服务端你想要哪个内容。那么要把这些信息以一种什么样的格式放到请求里去呢?这就是HTTP
协议要解决的问题。也就是说,HTTP
协议的本质就是一种浏览器与服务器之间约定好的通信格式。那浏览器与服务器之间具体是怎么工作的呢?
2. HTTP 工作原理
从图上你可以看到,这个过程是:
- 用户通过浏览器进行了一个操作,比如输入网址并回车,或者是点击链接,接着浏览器获取了这个事件。
- 浏览器向服务端发出
TCP
连接请求。 - 服务程序接受浏览器的连接请求,并经过
TCP
三次握手建立连接。 - 浏览器将请求数据打包成一个
HTTP
协议格式的数据包。 - 浏览器将该数据包推入网络,数据包经过网络传输,最终达到端服务程序。
- 服务端程序拿到这个数据包后,同样以
HTTP
协议格式解包,获取到客户端的意图。 - 得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态结果。
- 服务器将响应结果(可能是
HTML
或者图片等)按照HTTP
协议格式打包。 - 服务器将响应数据包推入网络,数据包经过网络传输最终达到到浏览器。
- 浏览器拿到数据包后,以
HTTP
协议的格式解包,然后解析数据,假设这里的数据是HTML
。 - 浏览器将
HTML
文件展示在页面上。
3. HTTP 请求响应实例
在浏览器和HTTP
服务器之间通信的过程中,首先要将数据打包成HTTP
协议的格式,那HTTP
协议的数据包具体长什么样呢?
可以看到,HTTP
请求数据由三部分组成,分别是请求行、请求报头、请求正文。
当这个HTTP
请求数据到达Tomcat
后,Tomcat
会把HTTP
请求数据字节流解析成一个Request
对象,这个Request
对象封装了HTTP
所有的请求信息。接着Tomcat
把这个Request
对象交给Web
应用去处理,处理完后得到一个Response
对象,Tomcat
会把这个Response
对象转成HTTP
格式的响应数据并发送给浏览器。
再来看看HTTP
响应的格式,HTTP
的响应也是由三部分组成,分别是状态行、响应报头、报文主体。
4. Cookie 和 Session
我们知道,HTTP
协议有个特点是无状态,请求与请求之间是没有关系的。这样会出现一个很尴尬的问题:
Web
应用不知道你是谁。比如你登陆淘宝后,在购物车中添加了三件商品,刷新一下网页,这时系统提示你仍然处于未登录的状态,购物车也空了,很显然这种情况是不可接受的。因此HTTP协议需要一种技术让请求与请求之间建立起联系,并且服务器需要知道这个请求来自哪个用户,于是Cookie
技术出现了。
4.1 Cookie 技术
Cookie
是HTTP
报文的一个请求头,Web
应用可以将用户的标识信息或者其他一些信息(用户名等)存储在Cookie
中。用户经过验证之后,每次HTTP
请求报文中都包含Cookie
,这样服务器读取这个Cookie
请求头就知道用户是谁了。Cookie
本质上就是一份存储在用户本地的文件,里面包含了每次请求中都需要传递的信息。
4.2 Session 技术
由于Cookie
以明文的方式存储在本地,而Cookie
中往往带有用户信息,这样就造成了非常大的安全隐患。
而Session
的出现解决了这个问题,Session
可以理解为服务器端开辟的存储空间,里面保存了用户的状态,用户信息以Session
的形式存储在服务端。当用户请求到来时,服务端可以把用户的请求和用户的Session
对应起来。那么Session
是怎 么和请求对应起来的呢?答案是通过Cookie
,浏览器在Cookie
中填充了一个Session ID
之类的字段用来标识请求。
具体工作过程是这样的:服务器在创建Session
的同时,会为该Session
生成唯一的Session ID
,当浏览器再次发送请求的时候,会将这个Session ID
带上,服务器接受到请求之后就会依据Session ID
找到相应的Session
,找到Session
后,就可以在Session
中获取或者添加内容了。而这些内容只会保存在服务器中,发到客户端的只有Session ID
,这样相对安全,也节省了网络流量,因为不需要在Cookie
中存储大量用户信息。
4.3 Session创建与存储
那么Session
在何时何地创建呢?当然还是在服务器端程序运行的过程中创建的,不同语言实现的应用程序有不同的创建Session
的方法。在Java
中, 是Web
应用程序在调用HttpServletRequest
的getSession
方法时,由Web
容器(比如Tomcat
)创建的。
Tomcat
的Session
管理器提供了多种持久化方案来存储Session
,通常会采用高性能的存储方式,比如Redis
,并且通过集群部署的方式,防止单点故障,从而提升高可用。同时,Session
有过期时间,因此
Tomcat
会开启后台线程定期的轮询,如果Session
过期了就将Session
失效。
5. HTTP 状态码
6. HTTP 请求方法
7. 请求首部
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Enconding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
IF-None-Match | 比较实体标记(与IF-Match相反) |
If-Range | 资源未更新时发送实体Byte的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中URI的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP客户端程序的信息 |
8. 响应首部
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
ETag | 资源的匹配信息 |
Age | 推算资源创建经过时间 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认知信息 |
10. 实体首部字段
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Last-Modified | 资源的最后修改日期 |