网络基础
概述
计算机网络基础是指计算机网络的基本概念、原理、技术、协议等方面的知识体系。它是计算机科学与技术中的一门基础课程,涉及了计算机网络的组成、结构、通信方式、传输协议、网络安全等方面的知识,是理解和掌握计算机网络相关技术的必备基础。
网络组成部分
计算机网络是由多个硬件设备和软件组成的。
- 主机(客户端与服务端):负责收发信息。
- 路由器:负责转发主机间的信息。
- 网络协议:负责提供统一的格式,方便路由器或主机对信息进行编码与解码。
网络结构
网络结构指的是计算机网络中各个网络节点之间的物理和逻辑连接方式。
- 局域网(LAN):覆盖范围通常在一个建筑物或者校园内,由多个主机组成。
- 城域网(MAN):覆盖范围通常在一个城市或者城市群内,由多个局域网组成。
- 广域网(WAN):覆盖范围跨越多个城市、地区或国家,由多个城域网主城,即网络的网络。
信息交换方式
信息交换方式指的是通信网络之间进行数据传输和交换的方式和协议。
- 电路交换:通过在通信双方之间建立一个专用的物理电路,然后在该电路上进行信息传输。
- 分组交换:将需要传输的数据分成一组一组的小数据包,然后将这些数据包分别发送到目标地址。
- 二者区别:分组交换不会进行电路连接,也不会预留资源,接受到新的分组后,会加入输出队列按顺序输出,当队列满的时候,会丢弃新到分组,即发生
丢包
。
在计算机网络中,采用的都是分组交换,大的报文会分解成n个小的报文,小的报文会经过分组,通过网络送到路由器后,再由主机上的软件将分组拼成完整的报文。
网络分层
网络分层是一种将网络协议按照功能划分为多个层次的方法。
计算机网络分为五层,从低到高分别是:物理层、链路层、网络层、传输层、应用层。本节课主要关注上三层。
- 网络层:主要负责数据包在网络中的路由和转发。网络层的作用是将数据包从源节点传输到目的节点,通过寻址、分组和路由等机制实现数据传输的可靠性、高效性和灵活性。
- 运输层:主要负责数据的传输和流量控制。运输层提供端到端的可靠数据传输服务,能够确保数据从源节点传输到目的节点的完整性、可靠性和顺序性。
- 应用层:主要负责为用户提供各种网络应用服务。应用层包括一系列协议,如 HTTP,这些协议为各种网络应用程序提供了标准的接口和通信规则。
网络协议
协议是指在通信中规定的信息交换的方式、格式和顺序的一组规则和约定。
协议的存在依赖于连接。即两个实体之间必须可以相互交换信息,否则协议没有意义。协议定义了在俩个或多个通信实体之间交换的报文格式
和顺序
,以及报文发送和/或接收一条报文或其他事件所采取的动作。
标头与载荷
数据包通常由标头和载荷两部分组成。
- 标头(快递单):数据包的元数据,包含了数据包的一些控制信息和传输参数。通常包括源地址、目标地址、数据包长度等字段。标头的作用是帮助网络设备在传输数据时进行路由选择、传输控制和错误检测。
- 载荷(包裹内容):数据包中的实际数据,即应用程序要传输的信息。载荷的格式和内容取决于具体的应用程序。
以 HTTP 协议为例
HTTP是一种应用层协议,用于在 Web 浏览器和 Web 服务器之间传输超文本文档。
TCP 协议格式
TCP是一种面向连接的、可靠的传输协议,属于传输层协议。
小结
- 网络组成部分:由主机、路由器、交换机等组成
- 网络结构:网络的网络
- 信息交换方式:电路交换和分组交换
- 网络分层:分清职责,物理层、链路层、网络层、运输层和应用层
- 网络协议:标头与载荷
Web 中的网络
HTTP 协议
请求
首行为起始行,也叫请求行,包含请求方法、资源路径与 HTTP 版本。后续内容为固定格式的头部名称:头部内容
。
响应
首行为状态行,包含 HTTP 版本,状态码与状态信息。其中状态信息是可以自定义的。后续内容为固定格式的头部名称:头部内容
。
HTTP 连接模型
HTTP 协议使用了典型的请求-响应
模型,也就是说当客户端发起一个请求后,需要等待服务端先返回第一个请求的完整响应,客户端才可以发起第二个请求。
队头堵塞:当一个请求非常大或服务器需要很长时间进行处理时,第二个很小的请求仍然需要等待前一个请求结束后才能发出,这导致非常大的资源浪费,进而导致了完成所有请求所耗费的时间远大于其应耗费的时间。
HTTP/1.1
// main.js
console.log('hello world');
/* style.css */
body{
color: red;
}
假设上面俩段代码交错发送,客户端收到的内容将会是下面这样子:
body{
console.log('hello world');
color:red;
}
这种结果对于客户端来说,根本无法判断该流中的每一行是属于哪个请求的,因此也就没法实现多路复用
了。
HTTP/2 帧
在 HTTP/2 中,将多个 HTTP 请求拆分到帧(Frame)中,每个帧可以携带来自不同HTTP 请求的数据。注意,这里的帧和之前提到的链路层的帧不一样,虽然工作原理类似。
request=style.css,content='body{'
request=main.js,content='console.log('hello world');'
request=style.css,content='color: red;'
request=style.css,content='}'
用这种方式来组织一条 HTTP 连接上流数据的传输方式,可以让 HTML 在连接上每个数据包都有自己的身份,也就是可以标识每个数据包来自哪个请求,进而实现多路复用
。
帧的结构
从 HTTP/2 中帧的结构可以看出
- Length(3 byte):表示帧的长度
- Type (1 byte):表示帧的类型
- Flags(1 byte):对应不同帧类型有不同的含义,用来传递当前帧的状态
- R(1 bit):保留位
- Stream Identifier(31 bit):代表该帧所属流的ID
- Frame Payload (....):当前帧的载荷
帧的好处
帧的引入不仅解决了多路复用
的问题,还带来了一些额外好处:
- 调整响应传输的优先级
- 头部压缩
- Server Push
既然 HTTP/2 已经解决了多路复用的问题,那为什么还需要 HTTP/3 呢?
原因如下:
- HTTP/2 还不够快
- HTTP/2 在 TCP 上仍然存在队头堵塞的问题
HTTP/3 QUIC
- Quick UDP Internet Connection
- 现存网络设备对 TCP 和 UDP 支持已经僵化
- UDP 不靠谱但是 QUIC 靠谱
- QUIC 可以为除 HTTP 协议意外的应用层协议提供支持
CDN
虽然各种协议经过多次改进后已经足够好了,但仍然有一些问题是协议无法解决的——比如物理极限、资源消耗和负载限制。
CDN 可以从物理层面解决 HTTP协议无法解决的问题,进而提升 Web 应用性能
CDN 的核心理念是缓存,即将远端的内容复制一份放在靠近用户的地方。
以下为一份通信网络示意图,假设我们的源服务器在北京、上海、广州、成都、长沙、兰州、长春。在使用 CDN 前偏远地区访问源服务器时有着较长延时,而在使用 CDN 访问后,图中所有地区访问源服务器都只需要最多跳跃俩次,这大大提高了访问响应速度。
DNS
即域名系统,是一个将域名和 IP 地址相互映射的分布式数据库
- 域名解析一般用网站自己处理
- 要加速的域名则重定向到 CDN 厂商的域名解析服务处理
- CDN 厂商根据来源确定最近的 CDN 服务器的 IP
- 用户直接访问最近的 CDN 服务器
基本缓存策略
- 拉取策略(Pull):也称为按需分发策略,CDN 服务器会在收到用户请求后,从源站服务器拉取内容并进行缓存,然后将内容返回给用户。
- 推送策略(Push):也称为预加载策略,CDN 服务器会从源站服务器获取内容,并将其主动推送到各个缓存节点上进行缓存。
WebSocket
- 有状态的持久连接:支持客户端和服务端之间的双向通信,并且可以在连接建立后一直保持打开状态。
- 服务端可以主动推送消息,无需客户端发起请求。
- 用WebSocket发送消息延迟比 HTTP 低:WebSocket 是建立在单个 TCP 连接上的,所以它可以更快地建立连接,避免了 HTTP 的三次握手和慢启动等过程,从而在发送消息时具有更低的延迟。
服务端代码
const{ WebSocketServer } = require('ws');
const wss = new WebSocketServer({ port: 8080});
wss.on('connection', function connection(ws) {
// 有新连接时监听来自客户端的信息
ws.on('message', function message(data){
// 打印收到的信息,再把消息原封不动地发回给客户端
console.log('received: %s',data);
ws.send(data);
});
)
客户端代码
const WebSocketServer = require('ws');
const ws = new WebSocket('ws://localhost:8080');
ws.on('open', function open() {
// 当连接建立时,向服务端发送一条消息
ws.send('something');
});
ws.on('message', function message(data) {
// 当收到来自服务端的消息时,打印出来
console.log('received: %s',data);
});
HTTP 与 WebSocket 的关系
HTTP 请求头
HTTP 响应头
WebSocket 客户端消息
WebSocket 服务端消息
小结
- HTTP 1 2 3 的演进历史
- CDN 解决了 HTTP 协议之外的问题
- WebSocket 从 HTTP 协议升级而来
网络安全
无论是HTTP还是UDP等等协议都是明文的,一条消息从一台电脑到另一台电脑中所经过的过程都可以看到消息的所有内容,甚至可以丢弃和篡改。明文会导致很多行为无法通过网络进行,比如银行转账。
三要素
- 机密性:攻击者无法获知通信内容。
- 完整性:攻击者对内容进行篡改时能被发现。
- 身份验证:攻击者无法伪装成通信双方的任意一方与另一方通信。
工具与约定
对称加密和非对称加密
- 对称加密:加解密用同样的密钥。
- 非对称加密:加解密使用不同的密钥(公钥和私钥),而且公钥加密只能用私钥解密、私钥加密只能用公钥解密。
密码散列函数(哈希函数)
- 输入:任意长度的内容。
- 输出:固定长度的哈希值。
- 性质:找到两个不同的输入使之经过密码散列函数后有相同的哈希值,在计算上是不可能的。
机密性
- 加密需要加密算法和密钥等信息(统称为秘密信息)。
- 网络是明文的,不安全。
怎么在不安全的信道交换秘密信息?
完整性和身份验证
完整性和身份验证相互关联。
- 蟹老板向银行发起了转账请求。
- 银行需要确认
- 这个请求真的是蟹老板发起的。
- 目标账户和转账金额没有被篡改。
如何实现机密性
- 已知:网络是明文的。
- 如果双方可以通过明文通信商量出秘密信息,那么攻击者也可以。
- 所以想要通过明文通信交换秘密信息,通信双方需要先有秘密信息,意思就是我们想要通过明文来交换密钥,就得有不会被攻击者知道的秘密信息。
如何实现完整性
- 密码散列函数性质:找到两个不同的输入使之经过密码散列函数后有相同的哈希值,在计算上是不可能的。
改进前
- 有明文 m ,密码散列函数 H
- 计算 H(m) 获得哈希值 h
- 将 m 和 h 组合成新信息 m+h
- 接收方拆分 m+h ,重新计算 H(m) 得 h' ,对比 h' 和 h
如果攻击者篡改了 m 重新计算 h,组合成新的 m+h ,对方就无法发现被篡改过了。
改进后
- 有明文 m ,密码散列函数 H,以及一个密钥 s
- 计算 H(m+s) 获得哈希值 h
- 将 m 和 h 组合成新信息 m+h
- 接收方拆分 m+h ,重新计算 H(m+s) 得 h' ,对比 h' 和 h
因此如果想要实现完整性,通信双方需要先有秘密信息。
如何实现身份验证
- 签名:用于鉴别身份和防止伪造。
- 非对称加密性质:加密、解密使用不同的密钥(公钥和私钥),而且公钥加密只能用私钥解密、私钥加密只能用公钥解密。
- 蟹老板用自己的私钥对信件进行加密,并发送给海绵宝宝。
- 海绵宝宝使用蟹老板的公钥进行解密,获得原文。
- 保证了机密性、完整性和身份验证。
- 数字签名:对明文内容的哈希值使用私钥加密,验证者使用公钥验证。
- 数字签名(指纹) = 私钥加密(密码散列函数(原文))
- 消息 = 原文 + 数字签名
- 一般用于对公开内容(如包含公钥的证书)进行数字签名,防止篡改。
以下俩点会形成套娃,可信的人验证蟹老板的公钥,更可信的人的公钥验证可信的人的公钥·······这个时候就需要有大哥站出来指认该签名就是他的,至此证书链套娃就解决了,而这个大哥就是根证书。
- 可信的人验证蟹老板的公钥。
- 那谁验证可信的人的公钥?
- 根证书是证书链的尽头。
- 验证的一连串证书称为证书链。
- 分发证书、验证证书的基础设施成为 PKI, Public Key Infrastructure。
证书链示例
HTTPS
把 HTTP 的明文换成密文,再验证身份,这就是 HTTPS。
HTTPS = HTTP + TLS TLS = 身份验证+ 加解密 身份验证靠 PKI
服务端身份验证靠 PKI,客户端身份验证靠 HTTP 协议。
小结
- 网络安全三要素:机密性、完整性和身份验证
- 在没有提前交换秘密信息的前提下,无法在不安全的信道交换秘密信息
- PKI 保证了普通用户不需要“面对面”和根证书机构交换根证书
- HTTPS 使用 PKI 完成了除客户端身份验证以外的特性,客户端身份验证靠 HTTP 协议实现