前言
本文梳理本人阅读《HTTP权威指南》遇到的相关问题与相关解答。若有错误请指正。
OSI参考模型
应用层,表示层,会话层,传输层,网络层,数据链路层,物理层
URL
<方案>://<用户>:<密码>@<主机>:<端口>/<路径>;<参数>?<查询>#<片段>
如果<标签>内有保留受限字符(比如密码有@),这些可通过encodeURIComponent转义。
DNS解析过程详解
为什么域名根服务器只能有13台呢?Avery Lu
状态码
重定向302、303、307的区分
【1】HTTP1.0(RFC1945)和HTTP1.1(RFC2616)对302的定义相同:如果客户端发出POST请求后,收到服务端的302状态码,那么不能自动的向新的URI发送重复请求,必须跟用户确认是否该重发,因为第二次POST时,环境可能已经发生变化(POST方法不是幂等的),POST操作会不符合用户预期。
【2】303和307是HTTP1.1新加的,是对原302状态码的细化。HTTP1.1规定303
处理应是:POST重定向为GET,307
处理应该是:POST重定向为POST(不一定是POST,非GET、HEAD请求即可)303和307的存在,归根结底是由于POST方法的非幂等属性引起的。
【3】但是浏览器实现HTTP1.0的302二次请求POST时未询问用户的情况下就变成GET(相当于303)
HTTP报文
HTTP报文组成(部分):
- 起始行
- 请求起始行:方法 URL HTTP版本
- 响应起始行:HTTP版本 状态码 原因短语
- 首部
- 通用首部: Date:Tue, 3 Oct 1974 02:16:00 GMT
通用缓存首部: Cache-Control
- 请求首部: Accept:*/*
From
Host
Referer
User-Agent
条件请求首部: If-Modified-Since
If-Match
安全请求首部: Cookie
Authorization
...
- 响应首部: Server:cloudflare-nginx
- 实体首部: Content-Type:text/html;charset-iso-latin-1
内容首部: Content-Length
实体缓存首部:ETag
Expires:Fri, 01 Mar 2019 13:37:39 GMT
Cache-Control:max-age=600
Last-Modified:在服务器最后被修改的时间
- 扩展首部
- 主体
ETag、Expires、Last-Modified解析
根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强制缓存和协商缓存 。
强制缓存
有3种:
1.不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求
2.存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
3.存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
控制强制缓存的字段分别是Expires和Cache-Control。到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差。所以同时存在时,只有Cache-Control生效。
浏览器的缓存存放在哪:
内存缓存(from memory cache):js和图片等
硬盘缓存(from disk cache):css文件
协商缓存
有2种:
1.协商缓存生效,返回304
2.协商缓存失效,返回200和请求结果
控制协商缓存的字段分别有:
Last-Modified / If-Modified-Since
服务端返回last-modified即最后修改时间,客户端下次发送if-modified-since(时间)后服务器比对。
Etag / If-None-Match
服务端返回Etag即唯一标识,客户段下次发送If-None-Match(标识)后服务器比对。
其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。
缓存优先级递减次序
no-store;(禁止保存临时文件,保护机密信息)
no-cache;(1.0的键名是Pragma,1.1是Cache-Control;在释放缓存之前,强制高速缓存将请求原始服务器验证。)
must-revalidate;(缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。)
max-age;(相对秒)
expries;(绝对日期时间)
参考:Cache-Control-MDN
承载TCP段的IP分组
TCP收到HTTP报文数据流后分段成IP分组,IP分组包括:IP分组首部
(20B)+TCP段首部
(20B)+TCP数据块
(0+B)
Nagle和TCP_NODELAY
Nagle算法鼓励发送最大传输单元(MTU:1500B),但确认分组延迟确认要等100-200ms。(为什么MTU值普遍都是1500?)
TCP_NODELAY方法即可禁用Nagle(nodejs默认开启)
socket.setNoDelay([noDelay])
request.setNoDelay([noDelay])
MSL和TIME_WAIT
MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现都必须选择一个确定的MSL值。RFC1122建议是2分钟。超过该数值会有TIME_WAIT累积与端口耗尽问题。
持久链接&管道化链接
HTTP/1.0+"Connection:keep-alive"
节省了打开链接和关闭链接的开销。
HTTP/1.1持久链接默认激活(前提:主体部分长度与Content-Length一致或分块传输编码),除非客户端发送报文有Connection:close。
HTTP/1.1允许在持久链接上使用请求管道,在响应到达之前可将多条请求放入队列,降低网络环回时间。(客户端不应在管道上发送POST这样非幂等请求,因为出错无法安全重试)
网关&隧道&中继
协议网关负责将一个协议转成另一个协议,常见的有HTTP/FTP、HTTP/HTTPS、HTTPS/HTTP。
资源网关负责HTTP请求与服务端应用转换,最流行的协议是CGI(输入请求,转交,响应),为避免每条CGI请求新开进程,出现了FastCGI作为持久守护进程。
隧道负责让HTTP应用访问非HTTP协议的程序。通过CONNECT方法请求隧道网关创建一条到达任意目的服务器端口的TCP链接,并对客户端和服务器之间的后续中继数据进行盲转发。
中继负责处理HTTP中建立连接的部分,然后对字节进行盲转发。
web爬虫
拒绝爬虫方法1:域名更目录放robots.txt,爬虫会根据它做选择。
# this robots.txt allows Slurp & Webcrawler to crawl
User-Agent: slurp
User-Agent: webcrawler
Disallow: /private
Allow: /public
User-Agent: *
Disallow:
拒绝爬虫方法2:robot-control标签index
|follow
|noarchive
|all
|none
<meta name="robots" content="noindex">
SSL和HTTPS
对称秘钥加密即编解码使用相同秘钥,如DES,3-DES,RC2,RC-4。缺点是发送者和接收者对话前要存有该秘钥。
公开秘钥加密使用非对称秘钥:客户端持公开秘钥,服务端持私有秘钥。避免了上述对称秘钥的缺点。如RSA。
对报文使用非对称秘钥数字签名,可以证明作者和防止篡改。
数字证书结构:版本号,序列号,签名算法,颁发者,有效期,对象名称,公开秘钥,其他扩展信息,数字签名。
OpenSSL是SSL和TLS协议以及一个全功能通用加密库的开源实现。
SSL握手需要做的工作:
交换协议版本号;选择一个两端都了解的密码;对两端的身份进行认证;生成临时会话秘钥,以便加密信道。
SSL握手过程:
1.客户端发送可选择的密码并请求证书
2.服务器发送选中的密码和证书
3.客户端发送保密信息,客户端和服务器生成秘钥。
4.客户端和服务器互相告知,开始加密过程。
HTTP2.0和HTTP1.X相比的新特性
二进制:HTTP1.x的解析是基于文本。文本的表现形式有多样性,而二进制实现方便且健壮。
多路复用:即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
header压缩:HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送:例如客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。