OSI 七层模型

daiweishuai

OSI 七层模型

OSI

Open System Interconnection适用于所有网络

1562979023227

七层网络协议模型

  • 应用层
  • 表示层
  • 会话层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层 七层网络

不同层中的称谓

  • 数据帧(Frame):是一种信息单位,它的起始点和目的点都是数据链路层
  • 数据包(Packet):也是一种信息单位,它的起始和目的地是网络层
  • 段(Segment):通常是指起始点和目的地都是传输层的信息单元。
  • 消息(message):是指起始点和目的地都在网络层以上(经常在应用层)的信息单元。

1563070928451

网络协议

  • HTTP HTTPS 是应用层协议
  • TCP UDP FTP TFTP 是传输层协议
  • IP ICMP 是网络层协议
  • ARP RARP 是数据链路层协议
  • 以太网协议是物理层协议

http 和浏览器出现之前,人们是如何浏览网页的?

TCP/IP 协议族

  • 70 年代,互联网出现,但是只能传输文本,不能传输图片、视频等
  • TCP/IP 协议(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)1971 年
  • TSMTP 协议(Trivial Simple Mail Transfer Protocol,简单邮件传输协议)1971 年
  • FTP 协议(File Transfer Protocol,文件传输协议)1971 年
  • Telnet 协议(Telnet,远程登录协议)1973 年

www 万维网

  • HTTP 协议(HyperText Transfer Protocol,超文本传输协议)
  • HTML 语言(Hyper Text Markup Language,超文本标记语言)
  • URL(Uniform Resource Locator,统一资源定位符)
    • http://user:password@host:port/path?query#fragment
  • HTTP 协议是建立在 TCP 协议之上的

HTTP 特点

  • 请求应答模式
  • 灵活可扩展
  • 可靠传输
  • 无状态(cookie、session)

HTTP 为什么不安全?

  • 泄露
  • 冒充
  • 篡改

对称加密(共享密钥加密)

  • DES Data Encryption Standard,数据加密标准
  • 秘钥 8 字节
  • encrypt(data, key) 加密
  • decrypt(data, key) 解密

非对称加密(公钥加密,私钥解密)

  • RSA Rivest-Shamir-Adleman
  • 公钥加密,私钥解密
  • 存储秘钥成本低(公钥只有一个,不用一个客户端生成一个秘钥)

证书

  • 提交:域名、公司名称、公司地址、公司电话、公司邮箱、公司营业执照等信息
  • 证书包含:颁发者、有效期、公钥、签名、有效期等
  • 正规的网站如果使用免费的证书,会让人觉得不靠谱,快要倒闭的感觉、形象不太好

中间人攻击 MITM Man In The Middle

  • 银行给客户端发送公钥时被劫持,客户端收到的公钥是中间人伪造的公钥,客户端用伪造的公钥加密数据,中间人用自己的私钥解密数据,然后用银行的公钥加密数据,银行用自己的私钥解密数据,这样中间人就可以看到客户端和银行的通信内容了
  • 伪造证书颁发机构(一般找权威的 GlobalSign Organization)
  • 如果骗子冒充你的身份,用他的域名去办证书会怎么样?证书需要提供公司的营业执照等信息,骗子提供不了银行等大公司的营业执照
  • 证书可以公开导出,骗子网站把你的证书放到他的网站上,冒充你怎么办?浏览器会检查域名,域名和证书不匹配,会提示证书不安全
  • 骗子把你证书里面的公钥换成他自己的怎么办?需要用指纹

如何保证公钥不被篡改?

  • CA 用哈希算法服务器公钥生成摘要(哈希值),加密后得到指纹
  • 客户端用哈希算法服务器公钥生成摘要(哈希值),解密指纹,对比摘要

如何证明身份?

  • 数字证书 Digital Certificate
  • 证书颁发机构 CA Certificate Authority

TCP 三次握手

在 TCP 三次握手中,SYN 是指"同步序列编号"(Synchronize Sequence Numbers),ACK 是指"确认序号"(Acknowledgement)。

  1. 客户端向服务器发送一个 SYN 报文段,表示客户端请求建立连接。
  2. 服务器收到客户端的 SYN 报文段后,向客户端发送一个 ACK 报文段,表示服务器已收到客户端的请求,准备好建立连接。
  3. 客户端收到服务器的 ACK 报文段后,也向服务器发送一个 ACK 报文段,表示客户端已收到服务器的确认,TCP 连接已经建立。

https

为什么用公钥加密却不能用公钥解密?open in new window

TLS 协议

TLS 的全称是 Transport Layer Security,中文名为传输层安全协议,是一种常用的基于加密的网络传输协议。TLS 协议是为了解决早期的 SSL 协议存在的安全漏洞和缺陷而被设计出来的,属于 HTTPS 协议的基础。

分层模型

下层是为上层提供服务的,上层提供请求和数据,下层进行处理

1562979945242

七层可以类比成给人写信

应用层代表写信的内容,表示层、会话层、传输层表示信的传输目标(地址、收件人),网络层是寻址、找目的地的过程,数据链路层和物理层表示真正传输的过程。

  • 物理层:传输是 0、1 传输,可能拿 0V 电压代表 0,5V 代表 1(网线、光纤、wifi 等实体),为上层数据链路层提供服务通道

  • 数据链路层:数据传输,需要物理层

  • 网络层:找到路线到目的地(最短),不关心中间传输的错误,不可靠,可靠性需要传输层。

  • 传输层:传输的过程中,每隔一个路线的节点或者一小段时间内,就向回返回一个到达的讯息,如果没有返回讯息,就会重新传递。直到到达目的地,返回一个到达目的地的讯息才算结束。在不可靠的网络层上,传递可靠的网络数据,这就是传输层

封装过程

1563059781060

客户端和服务器端交互模型

  • 打开一个浏览器, 在地址栏输入一个网址, 按下 ENTER 键, 到看到整页面, 中间都经历了哪些事情?

HTTP 请求阶段: 向服务器发送请求

  1. 浏览器首先向 DNS 域名解析服务器发送请求
  2. DNS 反解析: 根据浏览器请求地址中的域名, 到 DNS 服务器中找到对应的服务器外网 IP 地址
  3. 通过找到的外网 IP, 向对应的服务器发送请求(首先访问的是服务器的 WEB 站点管理工具: 准确来说是我们先基于工具在服务器上创建很多服务, 当有客户端访问的时候, 服务器会匹配出具体是请求哪个服务)
  4. 通过 URL 地址中携带的端口号, 找到服务器上对应的服务, 以及服务所管理的项目源文件

HTTP 响应阶段: 服务器把客户端需要的内容准备好, 并且返回给客户端

  1. 服务器端根据请求地址中的路径名称, 问号传参或者哈希值, 把客户端需要的内容进行准备和处理
  2. 把准备的内容响应给客户端(如果请求的是 HTML 或者 CSS 等这样的资源文件, 服务器返回的是资源文件中的源代码[不是文件本身])

浏览器渲染阶段

  1. 客户端浏览器接收到服务器返回的源代码, 基于自己内部的渲染引擎(内核)开始进行页面的绘制和渲染

    首先计算 DOM 结构, 生成 DOM TREE

    自上而下运行代码, 加载 CSS 等资源内容

    根据获取的 CSS 生成带样式的 RENDER TREE

    开始渲染和绘制 浅谈HTTP通信

  • 我们把完整的 请求+响应 称之为"HTTP 事务"

事务就是完整的一次操作, 请求和响应缺一不可

  • 一个页面完全加载完成, 需要向服务器发起很多次 HTTP 事务操作

一般来说: 首先把 HTML 源代码拿回来, 加载 HTML 的时候, 遇到 link/script/img[src]/iframe/video 和 audio[没有设置 preload='none']...都会重新和服务器端建立 HTTP 事务交互

特殊情况: 如果我们做了资源缓存处理(304), 而且即将加载的资源在之前已经加载过了, 这样的操作和传统的 HTTP 事务有所不一样, 他们是从服务器和浏览器的缓存中读取数据, 比传统的读取快很多

  • HTTP 报文

客户端向服务器发送请求, 以及服务器把内容响应给客户端的时候, 中间相互传递了很多内容(客户端把一些内容传递服务器, 服务器把一些内容响应给客户端), 我们把传递的内容统称为"HTTP 报文"

一个完整的 URL 各部分分析

下面拿网址展开知识:http://www.zhufengpeixun.cn:80/stu/index.html?name=xxx&age=25#teacher

  • URL/URN/URI

URI=URN+URL URI: 统一资源标识符 URL: 统一资源定位符 URN: 统一资源名称

  • 传输协议

用来传输客户端和服务器端交互的信息的 HTTP: 超文本传输协议(除了传递普通的文本, 还可以传递文件流或者进制编码等信息), 是目前最常用的 WEB 传输协议 HTTPS: 基于 SSL(Secure Sockets Layer 安全套接层)加密的 HTTP 传输协议, 比 HTTP 更加的安全(涉及支付的网站一般都是基于 HTTPS 完成的) FTP: 文件传输协议, 一般用来实现资源文件在服务器上的上传下载 (类似于快递, HTTPS 安全类似邮政, HTTP 类似普通的快递顺丰)

  • 域名(Domain Name)

一级域名(顶级域名): <www.qq.com> 二级域名: sports.qq.com 三级域名: kbs.sports.qq.com .com 供商用的国际域名 .cn 供商用的中文域名 .net 用于网络供应服务商(系统类的经常使用 NET 域名) .org 用于官方组织 .edu 用于教育元宵 .gov 用于政府机构

  • 端口号

用来区分同一台服务器上不同服务的标识(类似 WEB 服务管理器常见服务的时候可以指定), 不同服务之间一般是不能使用相同的端口号的 HTTP 默认端口号 80 HTTPS 默认端口号 443 FTP 默认端口号 21 如果当前网站服务, 采用的是协议对应的默认端口管理, 那么当用户输入网址的时候可以不指定端口号, 浏览器会默认对用户使用默认的端口传递给服务器

一台服务器上的端口号范围: 0~65535 之间

webStorm 预览页面: webStorm 把自己的电脑当做服务器, 在服务器上创建一个服务, 端口号是 63342, 自己电脑上的浏览器预览自己电脑上的服务, 属于本机服务请求, 用 localhost(127.0.0.1)本地域名即可

服务器上安装一款应用都可能会作为一个服务, 占用一个端口号

  • 请求路径名称

path pathname 例如: /stu/index.html 一般都是请求当前服务对应的项目目录中, stu 文件夹中的 index.html 页面. 但是也有特殊情况, 就时当前的 URL 是被"伪 URL 重写"的, 我们看到的 URL 请求其实不是真实的请求(例如: https://item.jd.com/4679424.htmlopen in new window 这个 URL 就是被重写的,

它的真实 URL 地址很可能是 https://item.jd.com/detail.jsp?id=4679424open in new window, 其实就是跳转到详情页, 通过问号传递不同的产品编号, 展示不同的产品详情信息, 但是 jsp 这种服务器渲染的动态页面不能被搜索引擎收录, 不利于页面的 SEO, 所以我们会把动态页面静态化, 这也就用到了 URL 重写技术)

例如: /stu/info 这种没有任何后缀信息, 一般都不是用来请求资源文件的, 而是用于 AJAX 数据请求的接口地址(如果后缀是.json 类的, 也是同理), 但是有一种除外 /stu/info/ 这种的很可能不是接口地址, 而是没有指定请求的资源名称, 服务器会请求默认的资源文件, 一般都是 index.html/default.html...

DHTML: 动态页面, 泛指当前页面中的内容不是写死的而是动态绑定的, 例如: jsp/.php/.aspx... 这些页面中的数据都是基于 AJAX 或者是后台编程语言处理, 由服务器端渲染, 最后把渲染后的结果返回给客户端呈现的

.jsp是 JAVA 用的, .php是 PHP 用的, .asp/.aspx是 C#或者.NET 用的

  • 问号传参及哈希值

?xxx=xxx&...#xxx 在 HTTP 事务中, 问号传参是客户端把信息传递给服务器的一种方式(也有可能是跳转到某一个页面, 把参数值传递给页面用来标识的) 哈希值一般都跟客户端服务器端交互没什么关系, 主要用于页面中的锚点定位和 HASH 路由切换

HTTP 报文

http请求报文格式

  • General 通用头
Request URL: http://www.zhufengpeixun.cn/  请求地址
Request Method: GET  请求方式:GET/POST/DELETE/PUT/HEAD/OPTION...
Status Code: 304 Not Modified   响应的HTTP状态码
Remote Address: 125.39.174.137:80  主机地址(服务器外网IP地址)
Referrer Policy: no-referrer-when-downgrade
  • Request Headers 请求头
GET / HTTP/1.1  起始行(描述当前请求的一些基本信息:用的是1.1版本传输协议进行内容传输的)
Host: www.zhufengpeixun.cn
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: ... cookie信息一般都是放到头文件中实现和服务器端的数据通信的
If-Modified-Since: Sun, 06 May 2018 10:02:42 GMT
  • Response Headers 响应头
HTTP/1.1 304 Not Modified  响应起始行(HTTP状态码)
Date: Tue, 22 May 2018 09:18:56 GMT  服务器响应内容时候的“服务器端时间”(客户端获取这个时间的时候已经和真实的时间产生误差了,因为服务器返回内容到客户端接收到,也是需要时间的),并且这个时间是格林尼治时间(比北京时间慢8小时,北京时间是GMT+0800)
Connection: keep-alive
ETag: "700a6f-17f43-56b86a77513d3"
Vary: Accept-Encoding,User-Agent
Server: yunjiasu-nginx  管理WEB服务的工具
CF-RAY: 41ee32c192db66b8-TSN

主要性能优化技巧

  1. 在 JS 中尽量减少闭包的使用(原因: 闭包会产生不释放的栈内存) A: 循环给元素做事件绑定的时候, 尽可能的把后期需要的信息(例如索引)存储到元素的自定义属性上, 而不是创建闭包存储 B: 可以在最外层形成一个闭包, 把一些后续需要的公共信息进行存储, 而不是每一个方法都创建闭包(例如单例模式) C: 尽可能的手动释放不被占用的内存 ...

  2. 尽量合并 css 和 js 文件(把需要引入的 css 合并为一个, js 也合并为一个), 原理是在减少 HTTP 请求次数, 尽可能的把合并后的代码进行压缩, 减少 HTTP 请求资源的大小 A: webpack 这种自动化构建工具, 可以帮我们实现代码的合并和压缩(工程化开发) B: 在移动开发(或者追求高性能的 PC 端开发, 例如百度首页), 如果 CSS 或者 JS 不是需要很多, 我们可以选择把 css 和 js 编程内嵌式(也就是代码直接写在 HTML 中)

  3. 尽量使用字体图标或者 SVG 图标, 来代替传统的 PNG 等格式的图片(因为字体图标等是矢量图(基于代码编写出来的), 放大不会变形, 而且渲染速度快, 相对比位图要小一些)

  4. 减少对 DOM 的操作(主要是减少 DOM 的重绘和回流(重排)) A: 关于重排的分离读写 B: 使用文档碎片或者字符串拼接做数据绑定(DOM 的动态创建)

  5. 在 JS 中避免"嵌套循环" (这种会额外增加很多循环次数) 和 "死循环" (一旦遇到死循环浏览器就卡壳了)

  6. 采用图片的"懒加载"(延迟加载) 目的是为了减少页面"第一次加载"过程中 HTTP 的请求次数, 让页面打开速度变快 步骤: 开始加载页面的时候, 所有的真实图片都不去发送 HTTP 请求加载, 而是给一张占位的背景图, 当页面加载完并且图片在可视区域内我们再去做图片加载

  7. 利用浏览器和服务器端的缓存技术(304 缓存), 把一些不经常更新的静态资源文件做缓存处理(例如: JS,CSS,静态图片等都可以做缓存) 原理是为了减少 HTTP 请求大小, 让获取速度更快

  8. 尽可能使用事件委托(事件代理)来处理事件绑定的操作, 减少 DOM 的频繁操作, 其中包括给每一个 DOM 元素做事件绑定

  9. 尽量减少 CSS 表达式的使用(expression)

#myDiv {
  position: absolute;
  width: 100px;
  height: 100px;
  left: expression(document.body.offsetWidth - 110 + "px");
  top: expression(document.body.offsetHeight - 110 + "px");
  background: red;
}
  1. CSS 选择器解析规则是从右向左解析
.container .link a {
  // 先找到所有的a, 再筛选是在.link样式类中的, 再次筛选是在.container样式类中的
  // 先找到的是所有的a, 操作起来是消耗性能的, 我们在使用css选择器的视乎尽可能减少对标签选择器的使用
}
  1. CSS 雪碧图技术(css sprite / css 图片精灵) 把所有相对较小资源图片汇总到一张大图上, 后期我们只需要把大图加载下来, 用背景定位的方式展示对应的小图即可
.bg{
    background:url('xxx.png');
}
.box1{
    background-position:xx xx;
}
.box2{
    background-position:xx xx;
}

<div class='bg box1'></div>
  1. 减少对于 cookie 的使用(最主要的是减少本地 cookie 存储内容的大小), 因为客户端操作 cookie 的时候, 这些信息总是在客户端和服务端传来传去
  2. 页面中的数据获取采用异步编程和延迟分批加载 使用异步获取数据, 是为了降低 HTTP 通道的堵塞, 不会因为数据没有请求回来耽误下面信息的渲染, 提高页面的打开速度(我们可以这样处理: 需要动态绑定数据的区域先隐藏, 等待数据返回并且绑定完成后再让其显示) 延迟分批加载类似于图片懒加载, 是为了减少第一次页面加载时候的 HTTP 请求次数
  3. 页面中出现音视频标签, 我们不让页面加载的时候就去加载这些资源(要不然页面加载速度会变慢) 方案: 只需要设置 preload='none'即可, 等待页面加载完成, 音视频播放的时候我们再去加载音视频资源
  4. 在客户端和服务端进行信息交互的时候, 对于多项数据我们尽可能基于 JSON 格式来进行传送(JSON 格式的数据处理方便, 资源偏小) 相对于 XML 格式的传输才会有这个优势
  5. 尽可能实现 JS 的封装(低耦合高内聚), 减少页面中的冗余代码(减少 HTTP 请求资源的大小)
  6. CSS 中设置定位后, 最好使用 z-index 改变盒子的层级, 让所有的盒子不在相同的平面上, 这样后续处理的时候, 性能有那么一点点的提高
  7. 在基于 AJAX 的 GET 请求进行数据交互的时候, 根据需求可以让其产生缓存(这个缓存不是 304 缓存), 这样下一次从相同地址获取的数据是上一次缓存的数据(但是很少用, 项目中一般刻意清除这个缓存的时候偏多)
  8. 尽量减少对于 filter 滤镜的使用(这个属性消耗性能较大一些)
  9. 在 CSS 导入的时候尽量减少使用@import 导入式, 因为@import 是同步操作, 只有把这个对应的 CSS 导入, 才会向下加载, 而 link 是异步操作
  10. 配置 ETag(有点类似于 304 缓存)
  11. 使用 window.requestAnimationFrame(JS 中的帧动画)代替传统的定时器动画
  12. 减少递归的使用, 避免死递归, 避免由于递归导致的栈内存嵌套(建议使用尾递归)
  13. 避免使用 iframe(不仅不好管控样式, 而且相当于在 a 页面中加载了其他页面, 消耗较大)
  14. 利用 h5 中提供的 loaclstorage 本地存储或者是 manifest 离线缓存, 做一些信息的本地存储, 下一次加载页面的时候直接从本地获取, 减少 HTTP 请求次数
  15. 基于 script 调取 JS 的时候, 可以使用 defer 或者 async 来异步加载
  • 重量级优化: 做 CDN 加速(烧钱机器)

额外技巧

  1. 我们一般都把 css 放到 body 上, 把 js 放到 body 下(原因: 让其先加载 css 再加载, 先加载 css 是为了保证页面渲染的过程中, 元素时带着样式渲染的, 而 js 一般都是用来操作 DOM 元素的, 需要等到元素加载完再操作)
  2. 能用 css 搞定的绝对不用 js, 能用原生 js 搞定的绝对不用插件, 绝对不使用 flash(除了音视频的低版本浏览器播放) css 处理动画等功能的性能优于 js, 而且 css 中的 transform 变形还开启了硬件加速
  3. js 中尽量减少对 eval 的使用, 因为 js 合并压缩的时候, 可能出现由于符号不完善, 导致的代码进行优先级错乱问题, eval 处理起来消耗的性能也是偏大一点的
  4. 使用 keep-alive 实现客户端和服务端的长连接
  5. 尽量使用设计模式来管理我们的代码(单例, 构造, Promise, 发布订阅), 方便后期的升级和维护
  6. 开启服务器端的 gzip 压缩(这个压缩可以有效减少请求资源文件的大小), 其实客户端的图片等资源也是可以进行压缩的(但是对于 24 位的位图, 压缩后可能会变模糊)
  7. 页面中不要出现无效的链接(利于 SEO 优化), 还有其他技巧: 提高关键字曝光率, img 需要加 alt, 设置 meta 标签, 标签语义化...
  8. 避免使用 with 语句(非常耗性能)
Last Updated 6/28/2025, 8:51:06 AM