HTTP简述
URI
URI(统一资源标识符) 分为URL(统一资源定位符) 与URN(统一资源名)。
URL一般分为三个部分
- 方案,http:// 即访问资源使用的协议
- 服务器所在的Internet地址
- web服务器所在的某个资源
URN依旧处于实验阶段,现在几乎所有的URI都是URL,所以一般不区分URL与URI
事务
通过请求命令与响应结果,客户端获得想要的结果。
- 请求方法 GET,POST,PUT,DELETE,HEAD
- 状态码 1XX,2XX,3XX,4XX,5XX
报文
http报文是由一行一行的简单字符串组成的,而不是二进制数据,所以很方便程序员直接进行读写操作,http报文分为三个部分
起始行与首部字段都是纯文本类型,但是主体可以包含任何需要的数据,二进制数据或者文本都可以。HTTP 采用了MIME数据格式标签,使得能够传送多媒体内容。
- 起始行 请求报文中说明要做什么,响应报文中说明出现了什么情况
- 首部字段 键值对的形式
- 主体 包含所有需要的数据
连接
http是应用层协议,不需要考虑网络通信的具体细节。细节都有tcp协议进行处理。使用80端口进行http连接。
可以使用telnet来连接几乎所有的tcp服务器,包括http。只不过发送的数据需要符合http的格式。用来模拟http客户端
版本
- HTTP/0.9 只支持GET方法,只用于获取简单的HTML对象
- HTTP/1.0 添加了版本号,HTTP首部,多媒体等
- HTTP/1.1 重点在于校正HTTP设计中的结构性缺陷,明确语义,添加了基于口令基本认证的方法,得以支持访问控制
- HTTP/2.0 重点在于性能的大幅度提升
结构组件
- 代理 接收所有的请求或响应并转发
- 缓存
- 网关 通常用于将http协议与其他协议进行转换
- 隧道
- Agent代理 用户代理,web浏览器,爬虫等
URL与资源
URI 是统一资源标识符
URL通过描述资源位置来标识资源,而URN通过描述资源名字来标识资源
语法
URL语法:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
最重要的三个部分,scheme方案 host主机 path路径
需要说明的是,frag是在客户端部分进行处理的,服务器负责处理全局的对象
快捷方式
URL可以分为相对URL和绝对URL。
使用相对URL需要先设置一个baseURL,使得获取相对定位。在解析时还需要将相对URL解析成为绝对URL。
浏览器会将浏览过的历史记录下来,在需要的时候进行自动的url扩展,得以自动补全。
编码机制
通过编码,进行转义,使得在URL中表示各种不安全的字符。
通常使用的转义符号有
- %
- /
- #
- :
- ;
常用方案
- HTTP
- HTTPS
- FTP
- mailto
- file
- news
- telnet
缺点
URL是通过资源路径来定位资源的,如果服务器将该资源的路径进行了修改,会导致之前的URL失效,无法继续定位
HTTP报文
HTTP报文流动方向
报文流入源端服务器,工作完成后,流回Agent代理中
所有的报文都是下游流动
组成部分
HTTP报文由三个部分组成
- 对报文进行描述的起始行
- 包含属性的首部块
- 可选,包含数据的主体
起始行 | HTTP/1.1 200 OK | ||
---|---|---|---|
首部 | Content-type: text/plain Content-length: 19 |
||
主体 | Hi! |
分类
所有的http报文可以分为两类,一是请求报文,二是响应报文。二者结构相同。
请求头
方法
客户端希望服务器执行的操作,GET,PUT,DELETE,POST,HEAD
请求URL
版本
状态码
原因短语
状态码
范围 | 已定义范围 | 分类 | ||
---|---|---|---|---|
100-199 | 100-101 | 信息提示 | ||
200-299 | 200-206 | 成功 | ||
300-399 | 300-305 | 重定向 | ||
400-499 | 400-415 | 客户端错误 | ||
500-599 | 500-505 | 服务器错误 |
首部
一些键值对的列表,添加附加信息。
分类
通用首部
可以出现在请求报文和响应报文首部中的。例如Date
请求首部
提供更多请求信息
响应首部
提供更多响应内容
实体首部
描述主体长度内容,或者资源自身
扩展首部
规范中没有定义的部分
方法详解
安全方法
HTTP中定义了一系列安全方法。GET和HEAD被认为是一种安全方法,这意味着使用GET或者HEAD的请求不会产生什么动作。HTTP/1.1 要求服务器必须实现GET与HEAD方法。
常用方法,GET,POST,HEAD,
了解GET与POST之间的区别。
…
连接管理
HTTP协议是基于TCP连接的。确保连接中数据不会丢失损坏,失序
HTTPS是在HTTP的基础上添加了一层SSL/TSL封装
TCP是分组连接,一个发送的数据可能会被分成多个TCP数据包进行分组传送。
TCP通过4个参数建立唯一通道
<源地址,源端口,目的地址,目的端口>
TCP连接
TCP三次握手
socket连接编程
HTTP基于TCP连接,所以事务上的性能很大一部分取决于底层TCP通道的性能。往往HTTP时延是由tcp网络延时造成的。
首先是通过DNS解析网络IP地址,然后建立TCP连接。
HTTP性能聚焦
- TCP连接建立握手
- TCP慢启动拥塞控制
- 数据聚焦Nagle算法
- 捎带确认的TCP延迟确认算法
- TIME_WAIT时延和端口耗尽
TCP连接建立握手
进行HTTP连接时需要先建立连接,这之间就存在握手时延。如果HTTP本身只传递少量数据的话,建立握手的时延就比较可观了。
延迟确认
TCP本身具有丢失重传机制来确保数据能够正确获得。如果发送者没有在指定时间内收到来自接收方的确认帧,则会认为该数据已经丢失,即开始重传。
大多数TCP采用延迟确认算法,在一定时间内的确认帧会放在缓冲区中,寻找能够携带的输出分组,如果一定时间内没有输出分组,则确认信息放在单独分组中传送。而由于HTTP本身的双峰特征,输出分组并没有很多,所以延迟算法一定程度上造成了时延。
TCP慢启动
TCP具有拥塞控制的功能,在一开始建立连接发送数据的时候,会限制本身的最大传送数据量,如果传输成功,则会逐渐提高传输速度。用于方式因特网的突然过载和拥塞。
例如先发送一个数据,然后两个,四个,逐步增加。
基于这种特性,已经进行过数据交换的连接传输速度比新连接要快一些。
Nagle算法和TCP_NODELAY
TCP本身有一个数据流接口,可以传送任意长度的数据。但是每个TCP的首部都有至少40字节的数据,所以如果大量发送少量数据,网络性能会严重下降。
所以Nagle算法会尽量将多个数据拼接在一起然后一起发送。这就造成了之前的数据会被延迟发送。特别是当剩余数据不足以达到算法的发送低值时,需要等到算法的设定时间后才会被发送。
可以配置禁用Nagle算法,但是同时应该确保发送的TCP分组中有大量数据。
TIME_WAIT累积与端口耗尽
当某个TCP端口关闭TCP连接的时候,会在内存中维护一个小的控制块,确保在一定时间内不会创建相同地址,端口的连接。在性能基准环境下,可能就会成为性能的限制。
每当客户端连接到80端口后,会获得一个新的端口,以实现连接的唯一性。但是由于可用源端口数量有限,在一定时间内可能会被限制不能再使用,就有可能遇到端口耗尽的问题。
即使没有端口耗尽的问题,也要考虑,大量连接处在打开状态,或处于等待状态,内存中分配了大量的控制块。会影响系统速度。
HTTP连接处理
Connection首部
###串行事务延时处理
如果只对连接进行简单管理,假设一个Web网页嵌入3个图片,则浏览器需要发起多个HTTP请求来显示页面。如果每个请求都串行建立新连接,则连接延时和慢启动就会叠加。
对此,可以采用并行连接,持久连接,管道化连接的方式处理
并行连接
浏览器开启多个TCP连接请求数据,但实际速度不一定更快。打开大量连接会消耗内存资源从而引发自身的性能问题。
持久连接
对于连到同一个站点的连接,浏览器可以通过一个TCP连接获取多个数据,这个方法在HTTP2.0中有所体现。
但是使用持久连接,需要注意,有可能出现大量空闲连接,消耗性能
持久连接有两种方案
HTTP/1.0 keep-alive
HTTP/1.1 persistent
Keep-Alive
Keep-Alive并不是默认开启的,需要有请求首部来显式要求
在代理中可能出现问题
persident
HTTP/1.1中默认开启
管道化连接
在响应到达前,可以先将多个请求放入队列中。可以减少网络环回时间。但是客户端需要做好随时断开连接,处理已发送尚未响应的请求。
关闭连接
Web服务器
Web服务器实现了HTTP和相关的TCP连接处理。负责管理Web服务器提供的资源,以及对Web服务器的配置、控制及扩展管理。
建立连接
处理新的连接,解析出IP地址,将连接加入Web服务器列表中。
接收请求报文
解析报文,读取内部控制字段和主体内容。
处理请求
对资源的映射和访问
构建响应
发送响应
记录日志
Web代理
Web代理服务器是网络的中间实体。位于客户端和服务器之间,在各端点间来回传送报文。
HTTP代理既是客户端又是服务器,需要同时处理请求和响应。
代理可以看到并接触所有流经的HTTP流量,所以代理可以监视和修改所有流量。
可以通过代理实现很多功能。
私有代理和公有代理
众多客户端共享的代理是公有代理,而私有代理仅被一个客户端使用。
代理与网关的区别
代理连接的是两个或者多个使用相同协议的应用程序,而网关连接的则是两个或者多个使用不同协议的端点。网关负责进行协议的转换。
原理
- 在客户端中设置代理。
- 修改网络
- 修改DNS
- 修改Web服务器,使用重定向命令。
URI 代理需要对URI进行处理
在设置代理的情况下,客户端会发送完整URI。
在没有设置的情况下,客户端只会发送部分URI,因为默认接收方已经知晓地址和端口。
在虚拟主机的配置中,也会出现类似的问题。即缺少方案,缺少主机,缺少端口。
不过代理是通过显式要求报文中使用完整URI来解决这个问题,而虚拟主机是通过HOST字段来承载主机和端口信息。
在有不可见拦截代理的时,对主机的解析会有所不同。因为对于客户端而言,是没有代理的,代理需要有很强的健壮性,能够处理各种各样的情况
报文追踪
via首部字段可以用来列出报文途中路过的中间节点。请求VIA与对应的响应VIA基本上是相反的,因为二者共用一个TCP连接。
TRACE 用户可以用来追踪代理链传输的请求报文,观察代理是如何处理报文的
缓存
对于同一份文档,多次传输占用了网络带宽,降低传输速度,加重服务器负荷。
将物理位置上远距离的文件保存在附近的网络服务器中,可以显著降低传输时延。
命中与未命中
时间
需要通过HTTP再验证,来保证缓存的新鲜度,即确保缓存的数据与网络上的数据依旧是一致的。可以通过条件首部字段,IF-MODIFIED-SINCE ,来询问服务器该资源在是否在某时间后发生了改变。
如果发生改变,则服务器就将新的数据传送回来。
如果未改变,服务器返回304状态码,表示NOT Modified
如果资源已被删除,返回404 NOT FOUND,缓存也将其副本删除。
文件本身 ETag
通过IF-NONE-MATCH
发送文件的标志ETAG给服务器,来确认是否发生变化
服务器处理缓存步骤
- 接收
- 解析
- 查询
- 新鲜度检测
- 创建响应
- 发送
- 日志
控制缓存
通过首部字段Cache-Control可以来控制缓存相关设置。
no-store
在使用完数据后,马上将数据从客户端中删除
no-cache
在获取使用数据后,可以将其缓存,但是每次使用前必须先向服务器验证该缓存的新鲜度。
关于广告
广告的点击一般是靠点击量的,缓存的存在,使得点击量会减少。
此时可能需要由客户端记录点击次数,然后发送给服务端
网关
协议网关
转换来自双方的不同协议,进行不同协议之间的通信。
常见的如:
- HTTP/FTP
- HTTP/HTTPS
资源网关
API就是所谓的通用网关接口。
隧道
可以通过HTTP应用程序访问使用非HTTP协议的应用程序。
Web隧道允许用户通过HTTP连接发送非HTTP流量,在HTTP上捎带其他协议数据。这类流量可以穿过只允许Web流量通过的防火墙。
使用connect建立HTTP隧道
CONNECT方法请求隧道网关创建一条到达任意目的的服务器和端口的TCP连接,并对客户端和服务器之间的后继数据进行盲转发。
中继
简单HTTP代理
Web机器人
在无需人类干预的情况下,自动进行一系列的web事务处理软件。
从一个站点进入另一个站点,获取内容,跟踪链接,并对数据进行处理。
爬虫
从根集出发,开始爬取数据。
链接提取
对爬到的HTML进行解析,得到其中的URL,并将链接添加待爬队列中。
还需要将相对URL转为绝对URL
避免环路
避免循环爬取页面的情况出现。
对已经提取过的网页,爬虫需要记录,来进行查找以避免重复请求。
需要实现快速搜索。搜索树或者哈希表。
URL别名
默认端口,默认页面,IP地址等的存在,使得可能出现多个不同的URL指向同一个页面资源,此时爬虫需要进行区别。
URL规范化可以在一定程度下解决这个问题
文件系统环路
需要爬虫本身实现循环检测机制
可采取的方案
规范化URL
广度优先遍历
节流,限制一段时间内机器人可以从一个站点获取的页面数量
限制URL大小
URL站点黑名单 对已知的某些会产生环路,存在陷阱的站点加入黑名单,避开请求
模式检测 对环路请求的模式特征进行监控
内容指纹 类似消息摘要
人工
拒绝机器人访问
拒绝机器人访问标准,自愿遵守的一个守则,如果存在该守则,则爬虫默认不去爬取页面。进行自我约束。
搜索引擎
HTTP-NG
HTTP/1.1 提供了很多强大的功能,但目前也出现了局限性,复杂,性能,传输依赖。
Http2协议是一个二进制协议,二进制更易于frame(帧 数据包)的实现,Http2有十个不同frame定义,其中两个最基础的对应于HTTP 1.1的是Data数据和HEADE头部,其后将描述。
frame是包含几个部分:类型Type, 长度Length, 标记Flags, 流标识Stream和frame payload有效载荷。
流标识是描述二进制frame的格式,使得每个frame能够基于http2发送,与流标识联系的是一个流,每个流是一个逻辑联系,一个独立的双向的frame存在于客户端和服务器端之间的http2连接中。一个http2连接上可包含多个并发打开的流,这个并发流的数量能够由客户端设置,这些流可能是打散了通过物理连接传输。
关键之一就是在 应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。
HTTP是一个无状态请求
但是有时候需要根据用户提供个性化网页,因此需要进行用户识别
- 承载用户身份信息的HTTP首部
- 客户端IP地址跟踪,通过IP地址识别用户
- 用户登录,使用认证的方式
- 胖URL,在URL中嵌入识别信息
- cookie
HTTP首部
From | 用户E-mail地址 | ||
---|---|---|---|
User-Agent | 用户的浏览器软件 | ||
Referer | 用户通过这个页面跳转而来 | ||
Authorization | 用户名和密码 | ||
Client-IP | 客户端IP地址 | ||
X-Forwarded-For | IP地址 | ||
Cookie | 服务器产生的ID标签 |
From,User-Agent,Referer都不足以实现可靠的识别。
客户端IP地址
利用IP地址来区别用户
限制:
- IP地址描述的是客户端机器,而不是用户。如果多个用户共用一个机器,此时无法区分
- DHCP动态IP配置,使得每个客户端有可能出现不同的IP地址
- NAT网络地址转换,使得IP地址难以识别
- 代理和网关的存在,服务器会看见代理的IP,而不是用户的IP
用户登录
用户主动登录,来判断用户是谁
胖URL
利用URL中记录的信息,来区别用户,对URL进行一些扩展,添加一些状态信息。
cookie
由服务器为了跟踪,而产生的一段字符串
会话cookie
临时使用的,在浏览器退出后就会被删除
持久cookie
存储在硬盘上,过期时间比会话cookie长很多。
会话cookie和持久cookie的唯一区别就是二者的过期时间
如果设置了Discard,或者没有设置过期时间,则这个就是会话cookie
cookie设置
使用set-cookie 首部。
不同的站点使用不同的cookie,可以通过设置cookie的域属性和路径属性,来使同一站点的访问使用同一cookie
domain=”xxx.com”; path=/path1/
secure 是否只有在SSL连接时才发送这个cookie
expiration 过期时间
allh 域内所有主机都获取cookie,还是只有指定了名字的主机获取
当进行重定向转移的时候,之前cookie依旧会被添加进后续的请求中。
cookie与缓存
在使用cookie的时候,需要注意这些内容可能是用户个人定制的,在某些时候,应该禁止浏览器缓存相关的数据。
HTTP基本认证
HTTP原生提供了一种认证机制。
服务器返回401状态码,表示该需要通过认证才能访问
通过AUTHENTICATE 首部字段,来进行验证
使用时,可以通过BASE4编码,来混淆账号密码。
WWW-AUTHENTICATE中包含了realm域信息,来明确需要访问的是哪个安全域。
这种验证,因为并不是加密验证,其实也是一种明文的信息进行了数据传输,容易被中间人获取。并不安全
摘要认证
摘要认证避免明文在网络上传输
可以有选择的防止对报文内容的篡改
防止恶意用户捕获并重放认证的握手过程
MD5对密码进行摘要,然后传输
服务器可以添加一个随机数给客户端,将随机数附在密码后面进行加密。可以有效防止将摘要记录后作为重放进行验证。
安全HTTP
HTTPS
使用SSL或者TLS, 传输层级别的密码安全层
HTTPS先将未加密的报文发给安全层,由其进行数据加密,然后再发送。
一般来说,加密过程对于HTTPS的应用层是隐藏的,应用只需处理自己业务逻辑即可。
HTTPS使用443端口
https 三次握手。SSL交换密钥
端口443 。https就是在http的基础上添加了ssl加密协议,利用密钥交换协议进行了密钥交换
验证CA证书。
具体分析。。。
1 | http://www.freebuf.com/articles/system/37900.html |
HTTPS代理
对于代理而言,一旦HTTP数据加密,代理就看不到相关的HTTP头信息,无法进行数据的转发。
一般此时,需要客户端提前将端口与地址等告知代理。以明文的形式
之后建立隧道,直接以隧道的模式进行交流