计算机网络概论 | 青训营笔记

290 阅读11分钟

这是参加「青训营 x 字节前端训练营」笔记创作活动的第 5 天的文章

pass: 只是一些记录,具体价值有待评估

课程介绍

这节课

  • 通过一个示例建立对计算机网络的整体认识
  • 建立对网络协议分层的认知
  • 分析HTTP1、2、3的关系
  • 介绍CDN运行的基本原理
  • 了解网络安全的最基本原则

这节课不会

  • 详细描述如何开发一个基于HTTP协议(或者其他协议)的网络应用
  • 深入介绍课程中所涉及协议的规范(Specification)内容和实现细节

蟹堡王帝国

小目标

蟹老板想挣一个“小目标”,制定了三步走战略

  1. 在比奇堡开通外卖
  2. 在北京和上海开分店
  3. 在全国开分店并开通外卖

比奇堡外卖

很快,蟹堡王火了,订餐用户越来越多,但出现了一个问题

章鱼哥:蟹堡王,请问要吃什么
龙虾拉里:“为什么我打不通?

因为人太多,龙虾拉里每次打电话时章鱼哥都在接听别的用户电话,于是电话占线打不通。

但是,聪明如你,能被这种困难所难倒吗

你发现,每次订餐的都可以被总结为三点

  • 谁吃 --> 派大星
  • 吃什么 --> 两个蟹黄堡和一个炸海草
  • 送到哪 --> 比奇堡石头屋

于是,每个用户想订餐时就使用传真机发送这三个消息到蟹堡王即可,章鱼哥终于解放了

北京和上海分店

生意越做越大,蟹老板打算在北京和上海开分店,当然,通信线路得从比奇堡拉过去。

image.png

之后这两个分店的客流量越来越多,店铺快要撑不住了,于是蟹老板打算继续开分店来减轻每个店铺的压力,当然这几家分店也得拉通信线路

image(1).png

于是问题出现了,通信线路难道还从比奇堡拉过去吗?(比奇堡在北大西洋,蟹老板抠门的性格肯定不会同意)
不,太浪费了,我们可以从大分店拉一条通信线路到小分店,这样就省去了很多建立通信线路的钱

而每家分店的销售数据可以这样

  • 来自 xxx蟹堡王
  • 发往 比奇堡蟹堡王
  • 内容 今日销售1000个蟹黄堡

总店的消息可以这样发

  • 来自 比奇堡蟹堡王
  • 发往 xxx蟹堡王
  • 内容 明日促销消息:全场8折

全国分店和通信网络

分店越来越多,全国也有了很多分店。当新增或搬迁分店的时候,都会向所有分店发送一次当前所有分店消息,这样用户在每个分店都能知道其他地方哪里有分店了

在其他城市开设分店当然也得拉一条线路,但是如果从比奇堡拉过去,很浪费(右边黄线交界处为比奇堡)

image.png

于是可以这样,杭州分店的线路从上海分店转过去,这样就又省了一笔钱(蟹老板狂喜)

image.png

原本这样

image.png

可以改成这样

image.png

这个时候,又发现一个问题

比奇堡居民居住分散,而城市中的小区密度较高,如果每家都直连蟹堡王,成本太高,聪明如你,当然想到了和开分店一样的搭通信线路的套路————小区中建立转发点,每个用户都与这个转发点链接即可。

然后蟹堡王越开越大,通信线路变成了这样

image.png

然后,以上这些可以类比为现实世界的终端(用户)、路由器、服务器(转发点)

image.png

网络基础

网络组成部分

  • 主机:客户端和服务端(负责提供信息或者接收信息)
  • 路由器(负责转发主机之间的信息)
  • 网络协议(负责统一格式便于主机和路由器对信息的编码与解码)

网络结构

可以称为:网络的网络

  • 比奇堡和小区网络:本地网络
  • 北京和上海分店+比奇堡:三个本地网络节点的网络
  • 全国通信网络:本地网络的网络

也就是:区域网络、城域网和广域网

信息交换方式

电路交换&分组交换

网络分层

物理层、链路层、网络层、运输层和应用层

  • 快递员不关心包裹内容
  • 卡车司机不关心车厢里拉的是什么
  • 高速公路不关心开的什么车

网络协议

协议的存在依赖于链接

协议的存在避免了以错误的方式解读数据

协议定义了在两个或多个通信实体之间交换的报文格式顺序,以及报文发送和/或接受一条报文或其他事件所采取的动作。

标头和载荷

收件人、寄件人关注:

  • 收件地址、寄件地址
  • 收件人、寄件人的姓名和电话
  • 包裹内容

而快递公司关注:

  • 收件人、寄件人关注的东西
  • 该由哪个集散点发出,哪个集散点收
  • 哪个网点派送

HTTP协议示例

image.png

链路层-本地帧头部

image.png

链路层-IP协议头部

image.png

运输层-TCP协议头部

image.png

应用层-HTTP协议头部

image.png

TCP协议格式

image.png

Web中的网络

HTTP

http报文=链路协议头+ip协议头+TCP协议头+http协议头+http正文

http1.1及以前版本中,头部和载荷是通过两个换行符和回车符进行划分的

image.png

HTTP连接模型

image.png

这种模型无法避免一种问题:队头堵塞(Head of Line Blocking)

而且HTTP1.1无法多路复用

例如你发送

console.log('hello');
body{
    color: red;
}

结果变成了

body{
console.log('hello');
    color: red;
}

HTTP2

于是在HTTP2中出现了帧的概念

request=style.css, content='body {'
request=main.js, content='console.log('hello');'
request=style.css, content='    color: red;'
request=style.css, content='}'
image.png image.png

前三个字节:载荷长度

image.png

第四个字节:类型

image.png

第五个字节:类型对应的Flags

image.png

第六到第九字节:

第1位:保留位

第2-32位:流ID

image.png

随后的8192字节:载荷

image.png

帧带来的额外好处

  • 调整响应传输的优先级
  • 头部压缩
  • Server Push

TCP

HTTP2:队头堵塞,但是在TCP上

TCP包0:包含了(包含了style.css的第1行内容)的HTTP2的帧
TCP包1:包含了(包含了main.js的全部内容)的HTTP2的帧
TCP包2:包含了(包含了style.css的第2行内容)的HTTP2的帧
TCP包3:包含了(包含了style.css的第3行内容)的HTTP2的帧

如果某个包丢包了,那客户端会向服务器请求再发送一次这个包

3 RTT启动

image (2).png

HTTP3

QUIC

image (3).png
QUIC-1 RTT
image (4).png
QUIC-0 RTT
image (5).png

CDN

你无法突破物理极限的

image (6).png

你的钱包够鼓吗?

image (7).png

你,够强大吗?

image (8).png

还得是我

CDN (Content Delivery Network),内容分发网络。CDN就是采用更多的缓存服务器(CDN边缘节点),布放在用户访问相对集中的地区或网络中。当用户访问网站时,利用全局负载技术,将用户的访问指向距离最近的缓存服务器上,由缓存服务器响应用户请求。

CDN:最多跳两次!

跳数城市
0北京、上海、广州、成都、长沙、兰州、长春
1天津、石家庄、沈阳、呼和浩特、南京、杭州、澳门、香港、南宁、福州、南昌、武汉、贵阳、拉萨、重庆、西安、西宁、银、哈尔滨
2太原、济南、郑州、乌鲁木齐、台北、昆明、海口、合肥

DNS劫持

image (9).png

近了!近了吗?

image (5).png
image (4).png

CDN:地主家也没有余粮了

image (6).png

WebSocket

  • 有状态的持久连接
  • 服务端可以主动推送消息
  • 用VebSocket发送消息延迟比HTTP低

服务端代码示例

const {WebSocketServer} = require('ws');
const wss = new WebSocketServer({port: 8080});

wss.on('connection', function connection(ws) {
    // 有新链接时监听来着客户端的消息
    ws.on('message', function incoming(message) {
    // 打印客户端发送的消息,并原封不动的返回给客户端
    console.log('received: %s', message);
    ws.send(message);
    });
});

客户端代码示例

const WebSocket = require('ws');

const ws = new WebSocket('ws://localhost:8080');

ws.on('open', function open() {
    // 当连接建立时发送一条消息给服务器
    ws.send('something');
});

ws.on('message', function incoming(data) {
    // 接收到服务器发送的消息
    console.log('received: %s',data);
});

升级!

image (7).png image (8).png

发送消息

image (9).png image (10).png

网络安全

网络安全三要素

  • 机密性:攻击者无法获知通信内容
  • 完整性:攻击者对内容进行篡改时能被发现
  • 身份验证:攻击者无法伪装成通信双方的任意一方与另一方通信

对称加密和非对称加密

  • 对称加密:加密、解密用同样的密钥
  • 非对称加密:加密、解密使用不同的密钥(公钥和私钥),而且公钥加密只能用私钥解密、私钥加密只能用公钥解密

密码散列函数(哈希函数)

  • 输入:任意长度的内容
  • 输出:固定长度的哈希值
  • 性质:找到两个不同的输入使之经过密码散列函数后有相同的哈希值,在计算上是不可能的

机密性

  • 加密需要加密算法和密钥等信息(统称为秘密信息)
  • 网络是明文的,不安全

完整性和身份验证

完整性和身份验证相互关联。

  • 蟹老板向银行发起了转账请求
  • 银行需要确认
    • 这个请求真的是蟹老板发起的
    • 目标账户和转账金额没有被篡改

如何实现机密性

  • 已知:网络是明文的
  • 如果双方可以通过明文通信商量出秘密信息,那么攻击者也可以
  • 所以想要通过明文通信交换秘密信息,通信双方需要先有秘密信息

如何实现完整性

image.png

  • 密码散列函数性质:找到两个不同的输入使之经过密码散列函数后有相同的哈希值,在计算上是不可能的
  • 有明文m,密码散列函数H,以及一个密钥 s
  • 计算H(m+s)获得哈希值h
  • 将m和h组合成新信息m+h
  • 接收方拆分m+h,重新计算H(m+s)得h',对比h'和h

所以想要实现完整性,通信双方需要先有秘密信息

如何实现身份验证

  • 签名:用于鉴别身份和防止伪造
  • 非对称加密性质:加密、解密使用不同的密钥(公钥和私钥),而且公钥加密只能用私钥解密、私钥加密只能用公钥解密
  • 蟹老板用自己的私钥对信件进行加密,并发送给海绵宝宝
  • 海绵宝宝使用蟹老板的公钥进行解密,获得原文
  • 保证了机密性、完整性和身份验证

数字签名

  • 数字签名:对明文内容的哈希值使用私钥加密,验证者使用公钥验证
  • 数字签名(指纹)=私钥加密(密码散列函数(原文))
  • 消息=原文+数字签名
  • 般用于对公开内容(如包含公钥的证书)进行数字签名,防止篡改

证书链 & PKI

  • 可信的人验证蟹老板的公钥
  • 那谁验证可信的人的公钥?
  • 根证书是证书链的尽头
  • 验证的一连串证书称为证书链
  • 分发证书、验证证书的基础设施称为PKI, Public Key Infrastructure
  • 所以想要实现身份验证,通信双方需要先有秘密信息,即根证书中的公钥

PKI保证了普通用户不需要“面对面”和根证书机构交换根证书

证书链示例

image (11).png image (12).png

HTTPS

把HTTP的明文换成密文,再验证身份,即HTTPS。

HTTPS = HTTP + TLS
TLS = 身份验证 + 加解密
身份验证PKI

HTTPS 使用 PKI 完成了除客户端身份验证以外的特性,客户端身份验证靠 HTTP 协议实现
简单来说就是:服务端身份验证靠PKI,客户端身份验证靠HTTP协议。

参考文献和书籍推荐