初步了解互联网:
//什么是互联网? 互联网的实现分很多层,每层都有自己的功能且依赖下层。 每一层为了实现各自的功能,约定大家需要共同遵守的“协议”,这些协议的总称就是“互联网协议”。 “互联网协议”对电脑如何连接和组网做了详细的规定,理解了这些协议,就理解了互联网的原理。 //什么是网络通信? 网络通信的本质就是交换数据包。 A向B发了个数据包,B又给A回了个数据包,AB间就实现了通信。 接下来要学习五层网络模型,就是要了解数据包的构成和通信流程。
五层网络模型:
实体层:
把电脑连接起来的物理手段,规定了网络的电器特性,用来传送 0 和 1 的电信号。
链接层:在“实体层”上方,确定 0 和 1 的分组方式。
//以太网协议 早期各家公司都有自己的电信号分组方式,后来 以太网协议 胜出成为主流。 //帧 一组电信号构成一个数据包,叫做 帧,每一帧由 Head 和 Data 组成。 Head(18字节),包含数据包的说明项(发送者、接受者、类型)。 Data(46~64字节),包含具体内容,数据长的话要分帧发送。 //MAC地址 连入网络的所有设备,都必须具有网卡接口,数据包必须从一块网卡,传送到另一块网卡。 MAC地址 就是网卡的地址,也就是数据包的发送地址和接收地址。 MAC地址 通常是一个12位16进制数,前6位为厂商编号,后6位为厂商网卡流水号。 每块网卡出厂时都有唯一 MAC地址(并非全球唯一,但基本不会撞)。 //广播 发送数据 - 向本网络内所有计算机发送,由计算机自行判断是否接收。 接收数据 - 判断 HEAD 中的接收地址,与自己的 MAC地址 是否相同,相同就接收。
网络层:引入一套“网络地址”,用来区分计算机是否属于同一子网。
//网络层的由来 以太网 以广播的形式发包,效率较低,无法应用于大型网络。 因此我们将互联网划分成无数个子网,子网内以广播形式发包,子网间以路由形式发包。 即,先用 网址 确定找到子网,再用 MAC地址 找到具体计算机。 //IP协议 IP数据包: 在数据发送时,IP数据包 会被直接放入 以太数据包 的 DATA 中。 HEAD - 20~40字节,包含版本、长度、IP地址等。 DATA - 具体数据。 IP地址: 规定 网址 的协议叫做 IP协议 ,所以 网址 就是 IP地址。 IP地址 由32个二进制数组成,习惯将其划分成四段十进制数。 IP地址 由两部分组成,前面的若干位代表网络,剩余的若干位代表主机。 //子网掩码 单从 IP地址 无法判断它的前多少位代表网络,所以引入 子网掩码。 子网掩码 由32个二进制数组成,网络部分全是1,主机部分全是0。 假设: IP地址为 - 192.168.0.1 子网掩码为 - 255.255.255.0 这就说明 - 该IP地址是 192.168.0.x 局域网中的一台主机 //路由 局域网间由路由器连接,路由器内有一张路由表,规定不同IP目的地数据包要发送到哪个网口。 我们要在网络中找到一个具体网址,就要先让路由器告诉我们这个网址对应的子网是谁。 可以把路由器理解为存储了一套指路牌的机器,这些指路牌可以帮助我们实现数据包的转发。 //ARP协议 发送数据时我们需要同时知道对方的 MAC地址 和 IP地址 ,通常 IP地址 已知。 取得MAC地址: 两台主机不在同一子网,将数据包传送到子网网关,让它处理。 两台主机在同一子网,可以用ARP协议取得对方MAC地址。 ARP数据包: 填写待查主机 IP地址,将 对方MAC地址 写成 FF:FF:FF:FF:FF:FF,说明自己是一条广播。 子网中的主机收到这条广播,取出其中的 IP地址 与自己比对,相同则回复本机 MAC地址。 注意: ARP协议是 链接层 协议,放这里说是为了方便理解,它的数据包随 以太数据包 发送。
传输层:“网络层”实现主机到主机,“传输层”实现端口到端口。
//端口 同一台主机上有多个程序需要用到网络资源,为了对应到具体程序,所以引入 端口 作为标记。 端口号是 0~65535 的整数,其中 0~1023 被系统占用,Unix系统把“主机 + 端口”叫做 套接字(Socket)。 //UDP协议:“传输层”最简单的协议 UDP数据包: 数据发送时将 UDP数据包 放入 IP数据包 的 DATA中。 HEAD - 8字节,定义发出端口和接收端口。 DATA - 具体数据。 UDP应用场景: App应用,DNS查找,广播传输,流媒体,线上游戏。 //TCP协议:TCP协议 可以看做是有确认机制的 UDP协议,更加安全可靠 TCP数据包: 数据发送时将 TCP数据包 放入 IP数据包 的 DATA 中。 TCP数据包在理论上没有长度限制,但为保证效率,它不会超过IP数据包的长度。 TCP应用场景: Web Browsing,E-mail,文件传输,线上游戏。 //TCP协议为什么更安全 SEQ: TCP会把数据分成合适大小的多个包,并允许一次性发送多个包。 为方便接收时按顺序还原,会给每个包编号(SEQ,数据包编号)。 假设:第一个包编号为1,负载200字节,则第二个包编号为201。 ACK: ACK中要携带:希望收到的下一个数据包的编号、接收方接收窗口的剩余容量。 是否掉包(举例): 主机A 向 主机B发包,主机B 成功接收1~4号包,5号尚未收到。 如果:后续 主机B 收到5号包,则回复的ACK指向6号包。 如果:后续主机B仍未收到5号包,则回复的ACK指向5号包。 若连续三次给主机A回复的ACK指向5号包,则认为5号包掉包重发。 慢启动: 服务器发包的理想情况是,在线路允许的情况下达到最高速率。 为了得知对方线路的理想速率,TCP引入了慢启动的概念。 首先慢速发送,根据丢包情况和ACK返回的窗口容量调整发送速率。 如果对方接受不了就慢发(流量控制),如果网络拥堵就慢发(拥塞控制)。 //TCP的三次握手与四次挥手 三次握手: 所谓三次握手,就是建立一个TCP连接时,需要客户端和服务端共发送3个包以确认连接建立。 ①. A向B发送SYN(同步标识)、自己的SEQ(数据包编号),A进入SYN-SENT状态。 ②. B向A返回SYN(同步标识)、ACK(确认消息)、自己的SEQ(数据包编号),B进入SYN-RCVD状态。 ③. A向B返回ACK(确认消息)、自己的SEQ(数据包编号),B收到后检查,检查成功后双双ESTAB-LISHED。 四次挥手: 所谓四次挥手,就是断开一个TCP连接时,需要客户端和服务端共发送4个包以确认连接断开。 ①. A向B发送一个 FIN,表示自己不会再向B传输数据,A进入FIN_WAIT_1状态。 ②. B收到FIN后返回ACK给A,B进入CLOSE_WAIT状态,A收到ACK后进入FIN_WAIT_2状态。 ③. B向A发送一个FIN,表示自己不会再向A传输数据,B进入LASH_ACK状态。 ④. A收到FIN后返回ACK给B,A进入TIME_WAIT状态,B收到ACK后进入CLOSED状态,2MSL后A也CLOSED。 //SYN Flood攻击: DoS攻击(拒绝服务攻击)的一种,利用TCP协议缺陷,发送大量伪造TCP请求使对方资源耗尽。 场景:假设第一次握手后客户端宕机则无法接到第三次握手信息。 正常情况:服务器重试,等待一段时间后丢弃该连接,这个时段长度为 SYN Timeout。 SYN洪水攻击:发送大量半连接,使服务器无暇理睬客户正常请求,或直接堆栈溢出崩溃。 解决方案:缩短SYN Timeout、设置SYN Cookie、用DCN防火墙拦截。 //DNS DNS是什么: 可以把DNS(Domain Name System,域名系统)想象成一个巨大的电话本。 某台服务器在网络里的真实地址是一个IP地址,但通常我们只知道域名。 DNS服务器上会存储“域名:IP”,通过DNS服务器把域名翻译成IP的过程就是域名解析(或叫DNS解析)。 域名层级: 大致结构:主机名.次级域名.顶级域名.根域名。 根域名:.root,所有域名的根域名是相同的,所以平时就省略了。 顶级域名(tld,top-level domain):如 .com .cn .net 等。 次级域名(sld,second-level domain):如 .baidu .sina 等,可自行注册。 主机名(host):如 www 等,这是用户在自己的域里为服务器分配的名称。 域名解析流程: 客户端主机: ①.根据输入网址提取出域名,先查本机Hosts。 ②.Hosts中有记录就直接返回,没有再向DNS服务器发起请求(没配DNS就完蛋)。 ③.DNS服务器没回应浏览器会报错:服务器挂了、DNS的IP不对、被GFW拦截了。 ④.DNS服务器有回应,就可以向其返回的IP地址发HTTP请求啦。 服务端主机: ①.首先访问该服务器,查询其中是否有相应的缓存,有就直接返回。 ②.没有缓存,就发送 根域名服务器 的IP给我们,让我们去那儿找。 ③.根域名服务器 里如果还没找到,就继续给我们 顶级域名服务器 的IP。 ④.依次类推,直到得到正确的IP为止,这个过程也叫做“DNS递归查询”。 安全问题: 域名劫持: 域名服务器上保存的域名记录,被认为修改成错的,这种情况就叫“域名劫持”。 场景:电信运营商(ISP)篡改自己的域名服务器记录。 办法:改用靠谱DNS服务器,向工信部投诉(400-881-0000),挂VPN或其他代理,全部强制HTTPS。 域名污染: 从发送DNS Query请求到有回应的这段时间,攻击者给我们返回假的应答,这种情况叫“域名污染”。 场景:党要求GFW(中国国家防火墙)全面封锁外网,最简单的办法就是污染该域名。 //CDN优化 同一个网址的服务可能分布在多个服务器,CDN(内容分发网络)能帮我们访问最合适的服务器。 用户访问网址,经过DNS解析后,将域名解析权交给CHAME指向的CDN专用的DNS服务器。 第一次重定向:CDN的DNS服务器将CDN的全局负载均衡设备的IP地址返给用户。 第二次重定向:向CDN的全局负载均衡设备发起请求,该设备经运算找到合适服务器并返回其IP。
应用层:“应用层”是直接面向用户的最高层,规定应用程序的数据格式,它的数据放在TCP的DATA部分。
//一次完整的HTTP请求过程 域名解析 - DNS分级查询,把网址翻译成IP地址。 建立TCP连接 - 3次握手,打开客户端与服务器间的连接通道。 客户端发起HTTP请求 - 发送request,告诉服务端自己想要什么。 服务端响应HTTP请求 - 发送response,返回数据和状态。 浏览器解析response中的HTML代码,并请求HTML中引用的资源(keep-alive的价值体现)。 浏览器对页面进行渲染和呈现。 //HTTP报文 request 数据格式: 请求行 - 请求类型、请求的URL、请求使用的HTTP协议版本。 请求头 - 服务器要使用的附加信息:User-Angent、Host等。 空行 请求体 - 可以使任何数据,可以在这里传参数。GET请求没有请求体,POST请求有请求体。 请求类型: GET - 完整请求一个资源 HEAD - 仅请求响应头 POST - 向指定资源提交数据并请求处理 PUT - 用客户端向服务器传送的数据取代指定文档 DELETE - 请求删除服务器上的指定文档 CONNECT - 让服务器代替用户访问其它网页,并把数据传回客户端 OPTIONS - 请求服务器告知其支持哪些功能 TRACE - 回显服务器收到的请求,用于测试和诊断 GET和POST的区别: 一个方法的本质是只读的,它就[安全] - GET、HEAD、OPTIONS、TRACE安全。 同一请求发送多次效果相同,它就[幂等] - GET、HEAT、PUT、DELETE、OPTIONS、TRACE幂等。 另外:GET、HEAD可缓存,POST有时可缓存,但大多数浏览器未实现POST缓存。 所以:GET - 请求获取指定资源,它安全、幂等、可缓存;POST - 根据请求对指定资源做处理,它不安全、不幂等、大部分浏览器中不可缓存。 注意:HTTP协议没有对GET和POST请求做出长度限制,只不过浏览器和web服务器限制了URI的长度。 URL/URI/URN: URI(统一资源标识符) - 在某一规则下把一个资源独一无二的标识出来。 URL(统一资源定位符)- 用定位的方式实现的URI。 URN(统一资源名称)- 用名称的方式实现的URI。 常见请求头: Accept - 告诉服务器,自己可以接收哪些MIME类型 Accept-Encoding - 告诉服务器,自己支持哪些压缩方式的文件 Accept-Language - 告诉服务器,自己支持哪些语言 Connection - 告诉服务器,自己支持keep-alive特性 Cookie - 每次请求都带上 cookie 方便服务器识别是否是同一客户端 HOST - 用来标识请求服务器上的哪个虚拟主机 User-Agent - 用户代理,一般情况下是浏览器 response 数据格式: 状态行 - HTTP协议版本、状态码、状态消息 消息头 - 客户端要使用的附加信息 空行 响应正文 - HTML等返回的正文 常见状态码: 1xx - 指示信息,表示已经收到,要继续处理 2xx - 成功 200 - OK,请求成功 3xx - 重定向 301 - Permanently Moved,永久重定向 302 - Temporarily Moved,临时重定向 304 - Not Modified,未修改(直接访问本地) 4xx - 客户端错误 400 - Bad Request,客户端请求有语法错误 401 - Unauthorized,请求未经授权 403 - Forbidden,服务端拒绝提供服务 404 - Not Found,资源不存在 5xx - 服务端错误 500 - Internet Server Error,服务器内部错误 502 - Bad Gateway,代理服务器联系不到后端服务器 504 - Gateway Timeout,后端服务器响应超时 常见响应头: Connection - 使用keep-alive属性 Content-Type - 返回内容的MIME类型 Content-Encoding - web服务器支持的返回内容压缩编码类型 Date - 原始服务器消息发出时间 Last-Modified - 请求资源的最后修改时间 Server - web服务器软件名称 MIME类型: MIME(Multipurpose Internet Mail Extensions)是描述消息内容类型的一种标准。 MIME消息能包含文本、图像、音频、视频等应用程序支持的数据类型。 HTTP请求规定,头信息是ASCII码,但后面数据可以是任何格式(HTTP/2开始就不是了)。 在request和response里写他们支持的MIME类型,是为了明确双方能解析什么。 //HTTP协议版本演进 HTTP/0.9 规定了GET请求,且只能响应HTML格式字符串(已淘汰)。 HTTP/1.0 加入了HEAD和POST请求,增加头信息,且能响应任何形式的数据。 缺点:每个TCP连接只能发送一个请求。 由于,TCP连接建立的成本很高,需要三次握手、慢启动、初始发送速率较差。 并且,在response得到HTML并解析,解析完成后需要请求HTML里引用的资源。 因此,有些浏览器加入非标准属性:Connection:keep-alive,要求服务器不关闭TCP连接。 这个属性在HTTP/1.0中未被标准化,在浏览器间的表现可能不一致,不能根本解决问题。 HTTP/1.1 加入了PUT、PATCH、OPTIONS、DELETE请求。 头信息增加HOST字段,用来指明服务器域名,使我们可以向统一主机上的不同网站发送请求(虚拟主机)。 持久连接: HTTP/1.1中将 Connection:keep-alive 标准化了,不写声明也能使TCP保持长连接。 非标准做法 - 客户端或服务端发现对方一段时间内没有活动,就主动关闭TCP连接。 标准做法 - 客户端在最后一个请求时发送:Connection:close,要求关闭TCP连接。 目前,针对同一个域名,大多数浏览器允许同时建立6个持久连接。 管道机制: HTTP/1.1中允许客户端同时发送多个请求,然后服务器按顺序回应。 且,要在response中加入Content-Length字段,让客户端知道下一个回应从哪开始。 分块传输编码: HTTP/1.1规定了 Transfer-Encoding:chunked字段。 使用Content-Length字段,需要在服务器回应前把所有数据生成,以便知道长度。 该字段表示回应字段由数量未定的数据块组成,使服务器可以生成一点儿发送一点儿。 每个非空数据块前有一个16进制值,表示该数据块长度,直到标识为0就表示发送完了。 利用这个字段,可以避免耗时过长的操作阻塞response。 痛点: 同一TCP连接中允许多次请求,但服务端需要按顺序回应,容易出现“队头阻塞”。 解决方案:减少请求数、多开持久连接。 前端做法:合并脚本、合并样式表、将图片迁入CSS代码、域名分片。 HTTP/2 HTTP/2 可以说是理想主义了,如果该协议普及了,很多前端的优化手段就用不着了。 二进制协议: 我们知道计算机只能识别二进制数,所以二进制解析起来比文本简单省时。 HTTP/1.1中,头信息是文本(ASCII码),数据体可以是文本或二进制。 HTTP/2中,头信息和数据体均为二进制,分别交头信息帧和数据帧,且允许定义额外帧。 多工通信: 多工表示双向实时通信 HTTP/1.1中,客户端可同时发送多个请求,但服务端要按顺序一一回应 HTTP/2中,客户端和服务端可同时发送多个请求或回应,避免“队头阻塞” 数据流: 每个请求或回应的所有数据包的集合叫一个数据流,每个数据流都有唯一的编号。 数据包不按顺序发送,为方便拼装要为每个数据包做标记并携带数据流编号。 客户端数据流编号为奇数,服务端数据流编号为偶数。 数据流发送到一半可以取消,客户端可以指定数据流优先级,优先级越高的越早得到回应。 头压缩: HTTP是无状态协议,每次请求都要附上所有信息,其中很多字段重复,浪费带宽。 HTTP/2允许头信息使用gzip或compress方式压缩后再发送。 HTTP/2允许客户端和服务端共同维护一张头信息表,为每个字段编号,之后用编号代替字段。 服务器推送: HTTP/2允许在未经请求的情况下,主动向客户端发送资源。 HTTP/2可以对页面中请求的静态资源进行预知,并将其与网页一同推送给客户端。 //HTTPS 对称加密和非对称加密: 加密就是让明文变成密文,解密就是让密文变成明文。 加解密的过程都需要一个叫 秘钥 的东西参与, 秘钥 可以看做是一个密码本。 对称加密 - 加密和解密用同样的秘钥。 非对称加密 - 加密和解密用不同的秘钥,公钥 加密过的东西,只有用对应的 私钥 才能解密。 其中,对称加密 速度快但安全性低,非对称加密 速度慢但安全性高。 证书体系(场景举例): 说人话版本: 原始介绍信 - A公司的甲要去拜访X公司,需要携带有A公司公章的介绍信,证明自己来自A公司。 原始介绍信痛点 - 与X公司有业务往来的公司很多,X公司可能无法分别识别他们各自的公章。 升级介绍信 - 我们找到权威的Y公司,给甲开一封带有Y公司公章和A公司公章的介绍信。 升级介绍信思路 - 甲拿着两封信到X公司,X处只要认识Y的公章,再比较两封信中X的公章是否相同。 翻译成技术语言: 证书 就是 原始介绍信 ,CA 就是Y公司,CA证书 就是 升级介绍信。 证书信任链 - CA证书 信任了 证书,这种信任关系可以嵌套,上层节点可信,则默认下层均可信。 SSL/TLS协议: Netspace发明了SSL协议,SSL协议被标准化后改名叫TLS协议。 可以把他们理解成同一个协议的不同阶段,也可直接写做SSL/TLS协议。 基本思路: 非对称加密 - 客向服索要公钥,客用公钥加密后把密文发给服,服用自己保管的私钥解密 。 如何保证公钥不被篡改 - 把公钥放在CA证书里,只要证书可信,公钥就可信。 如何提高效率 - 针对每次对话生成 session key,用session key加密信息,用公钥加密 session key。 基本流程: 客户端请求 - 发送:加密协议版本、支持的加密算法、支持的压缩算法、一个随机数。 服务端回应 - 发送:确认加密协议版本、确认使用的加密方法、服务器证书、一个随机数。 客户端回应 - 验证服务端证书通过后发送:编码变动通知、一个随机数、客户端握手结束通知。 服务端回应 - 用以上的三个随机数导出session key后发送:编码变动通知、服务器握手结束通知。 三个随机数: SSL协议中证书是静止的,随机数可以保证秘钥随机,客和服都要生成随机数才能保证每次秘钥不同。 SSL协议不相信每个主机能产生完全随机的数字,所以要加最后一个随机数(pre-master key)保证随机性。 HTTPS原理: HTTP协议是明文的,存在“被窃听、被篡改、被冒充”的风险; HTTPS可以看做是 HTTP over SSL/TLS。 即在TCP连接开启后,再开启SSL/TLS加密通道(传输层),让HTTP在加密通道中传输。 在加密通道中传输的就是正常的HTTP请求,只不过发送的内容通过 session key 加密过。 SSL/TLS协议也可以搭配给更多的应用层协议,如:FTP、SMTP、POP、Telnet等,和HTTPS原理相同。