发现写的好乱,内容基本是图解HTTP里的,但感觉讲的确实比较浅,以前我确实也是特意搜过这些,抓包的时候会用到吧~啊哈哈,真的是又乱又杂….
就先这样吧,比如SSL/TLS这种我在公众号写过了,这里就直接不多解释了,解释起来内容也挺多了…..
简单的HTTP协议
如果查看数据包,前两行应该是类似这样的:
1 | OPTIONS * HTTP/1.1 |
OPTIONS方法主要用来查询针对请求URL指定资源支持的方法,*代表的就是不是对特定资源,而是对服务器发起的请求
CONNECT方法要求在与代理服务器通讯时建立隧道,实现用隧道协议进行TCP通信,主要使用SSL/TLS协议把通信内容进行加密然后经过网络隧道传输:CONNECT 代理服务器名:端口号 HTTP版本
,后面也就一样了跟Host之类,如果响应为200,那么之后就进入网络隧道了
其实我们常用的也就是GET和POST方法,GET常用于获取,POST用于发送,明显的区别就是GET会把参数放在URL中传送,所以不安全内容大小也有限,但是速度快,POST相反,内容放在请求头中,相对安全
我们知道HTTP是无连接的协议,也就是每进行一次HTTP请求就要断开一次TCP连接,如果访问一个很多图片的网站,除了本身的获取HTML文件需要建立连接、发送请求/响应、断开连接,每一个图片的获取也要都来一遍,这就非常的浪费流量,并且还增加了服务器负载
所以在HTTP/1.1中有了持久连接,就是说,只要任意一端没有明确提出断开连接,则保持TCP连接状态,在1.1中默认都是持久连接,当然是需要客户端(比如浏览器)支持的
支持管线化后可以同时发送多个HTTP请求,使网页加载更快
但毕竟是无连接的协议,在网页跳转之后服务器就不认识你了,在需要记录登陆状态的网站,一般都需要使用Cookie来实现,当发送HTTP请求的时候携带Cookie,服务器再进行对比分析(通过Session),从而确认是谁发起的请求
具体的步骤是:
客户端请求—->服务器生成Cookie,并且通过响应返回给客户端—-客户端在请求中添加Cookie—->服务器知道是这家伙发送的请求
Cookie最大也只能是4KB~存在于请求头中
HTTP报文
HTTP报文有两部分组成,报文首部和报文主体,中间用空行(CR+LF)分割,以访问百度为例
请求报文:
1 | GET / HTTP/1.1 |
响应报文:
1 | HTTP/1.1 200 OK |
为了节省流量,服务器返回的主体可能会进行压缩,比如gzip, deflate方式等,还有一个是identity是不进行编码
- 分割发送
因为浏览器必须等到主体后才能加载,当一个网页很大时,那么加载就需要一定时间,页面一片空白,这时可以把主体部分进行分割发送,让浏览器先加载一部分
分块时每一块都会用16进制来标记块的大小,主体的最后一块使用0(CR+LF)
来标记 - 范围请求
也就是所说的断点续传,就是可以获取部分内容的请求,比如要获取5001-10000字节内的资源
在请求头中有:Range:bytes=5001-10000
与之对应的响应:Content-Range:bytes 5001-10000/10000
如果是获取从5000以后的全部可以直接5000-
这样写,以及可以多重范围:从开始到200以及300以后的就是:-200,300-
如果服务器支持会返回206 Partial Content
的状态码,不支持就返回200 OK并且会返回全部的内容 - 内容协商
就是根据你的环境返回最适合的内容,比如使用Accept-Language指明语言为中文,返回的就是中文网页
状态码
- 1XX: 信息
- 2XX: 成功
- 3XX:重定向
301:永久重定向
302:临时重定向
301、302、303返回时,几乎所有浏览器都会把POST改为GET,并删除报文中的主体部分,然后再次发送
虽然301、302的标准是进制改为GET的 - 4XX客户端错误
400:请求是不是写错了?服务器不理解
401:需要认证并且认证失败
403:不允许访问
404:没找到 - 5XX服务器错误
503:服务器正忙
详细参考:http://www.w3school.com.cn/tags/html_ref_httpmessages.asp
Web服务器的协作
一台Web服务器是运行部署多个域名的,虽然会被解析到同一台服务器,但是因为Host首部指定了唯一的域名地址,所以是可以正常解析的
- 代理
其实就相当于在服务器与客户端之间的中间人,负责转发数据包 - 网关
网关是转发其他服务器通信数据的服务器,接收到客户端发来的请求时,像自己拥有资源一样进行处理,客户端甚至感觉不到通信目标是个网关
网关顾名思义就是连接两个网络的设备,能在网络间转递数据包,主机则不能
利用网关也可以把HTTP请求转换为其他通信协议 - 隧道
简单说就是:相隔较远的服务器和客户端之间进行中转,并保持双方通信连接的程序,隧道本身是透明的
使用SSL等加密手段确保客户端和服务器进行安全的通信,隧道本身不会去解析HTTP请求,保持原样转发
隧道协议:将另一个不同的网络协议,封装在负载部分。使用隧道的原因是在不兼容的网络上传输数据,或在不安全网络上提供一个安全路径。
比如SSH隧道提供一个绕过防火墙,从而连到某些被禁止的互联网服务的的方法。
被封装的数据包在互联网上传递时所经过的逻辑路径被称为”隧道”。
隧道可在网络的任一层实现,最常用的是两层:数据链路层和网络层。 - 缓存
缓存都会有一个期限,以浏览器为例:当超过后浏览器会向服务器确认是否过期,如果确实失效,然后再重新获取
HTTP首部
主要是HTTP/1.1版本,每隔字段下面其实还细分很多参数,太多了就不贴了,用到的时候去找文档
贴下各首部主要是干什么的
通用首部字段
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为(no-cache可以缓存,但需要向服务器确认) |
Connection | 逐跳首部,连接的管理(Keep-Alive持久连接,close关闭连接) |
Date | 创建报文的日期时间 |
Pragna | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
请求首部字段
需要说明的是,除了下面的这些 HTTP 头是可以自定义的,在做 RESTful 的时候可能会用到;
在 HTTP 协议本身是没有限制 HTTP 头的大小。尽管如此,很多Web服务器、客户端和代理软件都对HTTP头的大小进行限制。如 Apache2.3 中,每个头的大小最多是8160个字节,一个请求里面最多包含100个头。
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型(xx;q=0.6, xxx表示权重) |
Accept—Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息(证书信息,会返回401) |
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 | 对请求中的URL的原始获取方法(防盗链) |
TE | 传输编码的优先级 |
User-Agent | HTTP客户端程序的信息 |
更多可参考:http://dafeizizhu.github.io/2013/07/12/http-header/
响应首部字段
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定的URL |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Rety-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体首部字段
首部字段名 | 说明 |
---|---|
Allow | 资源科支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对资源的URL |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
为Cookie服务的首部字段
首部字段名 | 说明 | 首部类型 |
---|---|---|
Set-Cookie | 开始状态管理所有的Cookie信息 | 响应首部字段 |
Cookie | 服务器接收到的Cookie信息 | 请求首部字段 |
Set—Cookie字段的属性
属性 | 说明 |
---|---|
NAME=VALUE | 赋予Cookie的名称和其值 |
expires=DATE | Cookie的有效期(若不mingque指定则默认为浏览器关闭前为止) |
path=PATH | 将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的目录) |
domain=域名 | 作为Cookie适用对象的域名(若不指定则默认为创建Cookie的服务器的域名,更安全) |
Scure | 仅在HTTPS安全通信时才会发送Cookie |
HttpOnly | 加以限制,使Cookie不能被JavaScript脚本访问 |
参考:https://ttop5.gitbooks.io/illustration-http/content/chapter6.html
Session与Cookie
关于这个在PHP(二)中提到过,这里再补充下
cookie保存在客户端,session保存在服务器端,session 可以放在 文件(默认)、数据库、或内存中都可以。
它们大多用来保持会话状态,流程类似:
客户端发送认证信息—->服务器认证后生成一个Session然后把ID存到Cookie里返回给客户端
客户端再次请求时携带Cookie—–>服务器验证后确认是真实用户
用户的多数信息可以放在Session中,一方面是因为安全问题,Cookie在客户端可以随意更改;另一方面Cookie只能保存4KB大小,Session随意了,因为一般不会放在内存中
我们知道HTTP是无连接的,当我们从A页面跳到B页面时,HTTP请求肯定是不同的,不同的HTTP请求之间肯定是无法共享数据的,但是Cookie在整个网站的域是可以随意访问的,所以可以利用Cookie来进行保持会话
Session生命周期
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet、PHP等后端程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
服务器会把长时间内没有活跃的Session从内存/硬盘删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
不过有人说当浏览器关闭后(非标签),Session就会销毁,这种是通过什么实现的我没找到….不过我知道服务器为保存SessionID而设置的Cookie是没有有效期的:
Cookie如果没有设置有效期,它的maxAge属性一般为–1,表示仅当前浏览器内有效,关闭浏览器就会失效。
服务器回写的 Cookie 名默认叫 JSESSIONID,注意是有path的,默认为当前应用
所以,当关掉浏览器这个Cookie就失效了,ID也就丢失了,服务器判断一段时间 Session 没有活跃,所以就删除了
更多内容参考:http://www.admin10000.com/document/7097.html
追加协议
HTTP/1.1也有很多的缺点:
- 一条连接只能发送一个请求
- 请求只能从客户端开始,客户端不能接收响应外的指令
- 发送冗长的首部,每次发相同的首部也是浪费流量
- 非强制压缩,有可能未经压缩就发送
如果是一个对实时更新要求比较高的网站,服务器端更新了在没有请求的情况下不能发送给客户端,只能客户端不断的去请求,发送大量重复的首部,每次返回的都是全部的内容
- Ajax
核心技术是XMLHttpRequest的API,通过JS脚本就可以和服务器进行HTTP通信,从而实现在加载完的页面上发送请求,并且进行局部更新 - Comet
通常,服务器收到请求,处理完毕后会立即返回响应,但是Comet会将响应置于挂起状态,一旦服务器更新了再返回响应,这样也就是说,一次连接的时间边长了
但是以上两种并没有解决HTTP本身的问题,还是会发送大量的重复首部,后来有了Google的SPDY
SPDY工作在会话层,也就是TCP(SSL)和HTTP之间,还是采用HTTP建立连接,考虑到安全性规定使用SSL,它做到了:
- 单路复用
在单一的TCP连接上可以处理多个HTTP请求 - 赋予请求优先级
- 压缩HTTP首部
- 推送功能
服务器可以直接发送数据给客户端,不用等待客户端的请求 - 服务器提示
主体提示客户端请求的所需资源,在客户端请求资源前就知道了资源的存在,减少了请求
WebSocket协议
也是为了解决HTTP协议的瓶颈,它支持发送任意类型的数据,推送功能,会一直保持连接状态所以也就可以进行全双工通信,可以直接向客户端发送数据
建立WebSocket还是用的HTPP,在首部加入Upgrade:websocket;Connection:Upgrade
,服务器收到后返回101 Switching Protocols
然后双方就开始使用WebSocket进行通信了
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~