一. 图解网络
-
为什么需要TCP/IP网络模型: 为了适应互联网环境下多种多样的设备, 设计的一套通用的网络协议
-
对于同一台设备进程间的通信方式: 管道, 消息队列, 共享内存, 信号量
-
TCP/IP网络模型的分层:
- 应用层: 用户能够直接接触到的层次, 互联网软件都是在应用层进行实现. 应用层专注为用户提供应用功能
- 应用层协议: HTTP, FTP, Telnet, DNS, SMTP等
- 应用层协议在操作系统中是工作在用户态, 传输层及以下的协议是工作在内核态
- 传输层: 为应用层提供网络支持, 只有两个典型的传输层协议: TPC/UDP
- TCP相比UDP的优势: 流量控制, 超时重传, 拥塞控制, 能够保证数据被可靠地传递给对方
- UDP的特点: 只负责发送数据包, 不保证数据包能够抵达, 实时性更好, 传输效率更高
- TCP的分段传输: 当数据包大小大于TCP最大报文长度(MSS长度), 会将数据包进行分段. 当在传输中出现分段损坏, 只需要重新发送损坏的分段
- 传输层的端口: 端口是在传输层进行维护的. 在物理机上端口是操作系统在进程运行时为系统分配的临时编号. 可以使用端口号判断信息是发送给哪个进程的
- 网络层: 典型网络层协议为IP协议. 其主要处理的问题是完成从一台机器传输到另一台机器间的路径选择
- IP协议包的大小为MTU长度, 其一般为1500字节. MTU长度是由于MAC协议限制的, 如果超长会进行拆分
- IP地址到物理机的映射: IP地址被分为四段, IPv4的每段长度为8位. 其中前三段为网络号, 第四段为主机号
- 从IP地址中提起网络号的方式是通过和子网掩码做且运算
- IP地址的路由能力: 路由的意义是找到目标地址的子网, 然后将数据包转发到对应的网络中
- 网络接口层(物理层): IP地址表示的网络是以太网, 以太网技术是一种在局域网内, 将附近的设备连接起来, 使其能够进行相互通信的技术.
- Mac地址: 用于表示网络接口, 交换机等物理硬件的地址. 通过ARP协议能够获取其他物理设备的MAC地址
- 应用层: 用户能够直接接触到的层次, 互联网软件都是在应用层进行实现. 应用层专注为用户提供应用功能
-
常见协议工作的网络层
- 应用层: FTP, SMTP, HTTP, IMAP4, POP3, SSH, RPC
- 传输层: TCP, UDP, DCCP, SCTP, RTP
- 网络层: IP, ARP(从IP地址中解析MAC), ICMP(ping命令使用的协议)
- 数据链路层:CSMA/CD(总线型网络碰撞检测协议)
-
从键入网址到网页显示期间发生了什么
-
URL解析: 通过数据文件路径名称请求服务器里的文件资源, 将URL中的参数整理为包中的参数进行发送
-
DNS查询: 通过专门的服务器保存Web域名和IP的对应关系.
- 域名的层次关系: 域名中字段靠右层次越高
- DNS服务器的树状结构:
- 根DNS服务器:
.
- 顶级DNS服务器:
.com
- 权威DNS服务器:
server.com
- 根DNS服务器:
- 查询DNS的执行流程
- 客户端向本地DNS服务器发送DNS请求
- 本地DNS服务器优先使用本地缓存, 如果无法找到会请求根域名服务器
- 根域名服务器返回
.com
顶级域名服务器的地址 - 本地DNS服务器访问
.com
顶级域名服务器 - 顶级域名服务器返回权威DNS服务器地址
- 本地DNS服务访问权威DNS服务器地址
- 权威DNS服务器返回IP地址
- 本地DNS服务器将IP地址返回客户端
-
协议栈传输
-
TCP: 进行可靠的数据传输
-
输入源端口号, 目标端口号, 包序号, 确认号, 状态位, 窗口大小
-
三次握手: 建立TCP链接的过程
- 开始状态: 客户端处于
Close
, 服务端处于Listen
状态 - 主动发起连接: 客户端主动发送
SYN
包, 然后处于SYN-SENT
状态 - 服务端收到发起的连接: 服务的返回
SYN + ACK
包. 服务端处于SYN-RCVD
状态, 客户端处于ESTABLISHED
状态 - 客户端发起ACK: 服务端收到客户端ACK后处于
ESTABLISHED
状态
三次握手的原因: 至少通过三次握手能够达到客户端和服务端的一发一收状态, 能够保证双方都有发送和接收能力
- 开始状态: 客户端处于
-
TCP状态的查看:
netstat -napt
通过该命令查看TCP连接状态 -
四次挥手: 断开TCP链接的过程
- 开始状态: A,B 均为
ESTABLISHED
状态 - A向B发送释放报文(
FIN = 1, SEQ = u
) 然后停止发送数据, 进入FIN-WAIT-1
状态 - B响应确认报文(
ACK=1 ack=u+1 seq=v
). B停止发送数据进入CLOSE-WAIT-2
状态, 并通知应用链路关闭 - 应用确认关闭后, B发送最终确认报文(
FIN=1 seq=w ack=u+1
), 进入LAST-ACK
状态 - A接受最终报文后返回确认报文(
ACK=1, seq=u+1, ack=w+1
), 进入TIME-WAIT
状态, B接受返回后进入CLOSE
, A等待2MSL
后进入CLOSE
状态
四次挥手的原因:
- A方主动关闭应用, 需要通知B端, 由B端通知应用关闭连接. 所以需要两个来回, 第一个来回确认B收到A应用关闭, 第二个来回确认A收到B应用已关闭
- 为什么需要等待
2MSL
: 因为A端发送的最终确认报文可能丢失, 如果丢失则会A已关闭连接而B未关闭连接, 导致同步出错. 另外可以防止AB建立新连接的时候网络中还存有上一会话的消息, 因为2MSL
可以保证来回两方向的消息都失效, 不会对下次连接造成影响
- 开始状态: A,B 均为
-
-
-
-
Linux系统如何收发网络包
- 使用网络协议栈对于消息进行层次化的封装. 除了网络接口层是通过帧头和帧尾进行封包以外, 其他数据是通过包头进行封装的
- 1. 能够得到的信息: - Socket层是运行在内核态中的 - ICMP是和IP层一起的网络层 - ARP是和MAC层一起的数据链路层
- Linux接收网络包的流程
- 网卡会将接受到的网络包写入指定的内存地址, 写入的内存结构是一个环形的缓冲区
- 网卡通知操作系统完成了数据包写入的操作:
- 最简的通知方式是由网卡发起中断
- 但是在高性能网络环境中频繁中断会导致CPU忙于处理中断,无法处理其他请求. 所以改为通过
NAPI中断 + 轮询
的机制进行数据的获取- 当网卡收到第一个数据包时会通过中断通知操作系统, 该中断会由物理中断处理函数进行拦截, 该函数会通知网卡后续收到的包不需要再次发送中断, 只需要直接写入内存即可
- 由物理中断线程发起软中断通知操作系统进行数据的处理
- 对于软中断的处理是通过ksoftirqd内核线程进行执行, 其会从内存中获取一个数据帧, 将数据帧的数据根据网络协议栈逐层处理
HTTP篇
-
HTTP面试过程中的六大类问题:
-
HTTP的基本概念
-
基本概念: HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」
-
超文本概念: 超越普通文本的数据, 是文字, 图片, 视频等的混合体. 能够通过超链接从一个超文本跳转到另一个超文本
-
常见的Http状态码:
-
1xx
表示协议处理的中间状态 -
2xx
服务器成功处理了客户端的请求200 OK
表示一切正常204 No Content
表示处理成功但是没有消息体206 Partial Content
表示需要HTTP进行分块下载或者断点续传, 表示Body数据不完全
-
3xx
表示客户端请求的资源发生了变动, 需要客户端使用新的URL请求资源, 也就是告知客户端需要重定向301 Moved Permanently
表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。302 Found
表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。
重定向数据包一般在响应头中有
location
字段, 用于浏览器自动的跳转 -
4xx
表示客户端发送的报文有问题, 服务端无法解析该报文 -
5xx
表示服务端内部处理出现问题, 或者是访问服务端的路由路径上出现问题
-
-
HTTP包中的字段:
- Host: 服务器主机名称
- Content-Length: 用于表示数据体长度的字段, 分割TCP数据流中的不同HTTP数据包
- Connection: 一般用于和服务器构建长连接, 使TCP链接能够在多个请求间复用
- TCP长连接的特点: 只要任何一端没有明确提出断开连接, 就保持TCP的连接状态
- Http/1.1版本中默认都是长连接
- Content-Type字段: 用于告诉客户端本次数据是什么格式的
- 例如:
Content-Type: text/html; Charset=utf-8
告知客户端其发送的是以utf8编码的http文本文件 - 客户端在发起http请求的时候可以通过 Accept字段表明自己可以接受哪些格式的数据
- 例如:
- Content-Encoding字段: 用于表示数据的压缩方式, 和客户端的
Accept-Encoding
形成一对
-
-
Get和Post
- Get请求的语义: 从服务器中获取指定的资源. 其参数一般都是写在URL中, 使用ASCII字符
- Post语义: 根据请求的负载, 对于指定资源做出处理
- 安全性和幂等性
- Get是只读的, 所以其是安全且幂等的, 所以可以在浏览器端对于Get请求进行缓存, 在代理上可以将Get请求进行路由
- Post请求不是只读的, 其可以基于提交的数据进行操作, 所以是不安全, 不幂等的, 一般而言不会将Post请求保存为书签
- 数据传输的安全性: Http中所有数据的传输都是明文的, 不论Get还是Post请求, 都能使用抓包查看数据. 如果想保证数据传输的安全性需要使用https
- Get请求中也可以携带Body, 但是一般而言其语义上不需要使用Body.
- Post请求中可以添加URL查询参数
-
Http的缓存技术
- Http中的缓存指的是对于一些幂等的操作, 可以将
请求-响应
的数据缓存在本地, 当再次调用的时候直接从本地进行读取 - http缓存的两种实现: 强制缓存, 协商缓存
- 强制缓存是指服务器在返回资源的时候通过
Cache-Control
和Expires
字段告知客户端可以缓存该资源, 由客户端根据这两个值判断如何缓存资源信息, 以及判断资源信息是否过期 - 协商缓存是指客户端在请求中同时发送资源的获取时间戳, 由服务器判断该资源在上一次获取到当前过程中是否发生过期. 通过
If-Modified-Since
字段和Last-Modified
字段判断资源是否过期Last-Modified
: 服务端返回的响应头部, 用于表示该资源的最后修改时间If-Modified-Since
客户端发送的请求头部, 用于表示该资源最后一次从服务器获取的时间- 如果客户端不需要重新获取资源则返回304, 如果需要重新获取资源则返回200
- 对于无法使用修改时间戳进行标记的数据, 可以使用
If-None-Match
字段和ETag
字段进行标记. 在客户端重新请求对象的时候, 将If-None-Match
的值设置为收到的ETag
值, 如果发现ETag
不一致则重新获取对象 - 为什么推荐优先使用
ETag
而不是If-Modified-Since
:- 可能会出现文件本身没有改变但是修改日期发生改变, 导致重复获取
If-Modified-Since
是秒级粒度的, 无法支持亚秒级的数据更新- 有些服务器无法精确获取文件的最后修改时间
- Http中的缓存指的是对于一些幂等的操作, 可以将
-
Http的特性
-
HTTP/1.1:
-
优点: 简单, 灵活, 易于扩展, 跨平台
其请求方法, 状态码, 头字段等信息可以由开发人员自由扩展
其工作在应用层, 其下层协议栈能够自由更换: Https是在Http和TCP层之间添加了SSL/TLS安全传输层
Http3.0选用了UDP协议作为底层的数据传输协议
-
缺点: 无状态, 明文传输
-
无状态: 虽然减少了服务器对于HTTP状态的记忆, 但是在完成一些关联性操作的时候会比较麻烦
处理无状态问题的最简单的方式是通过
Cookie
在请求和响应报文中通过添加Cookie信息用于表示客户端状态 -
明文传输: 传输过程中信息没有隐私, 能够被其他用户拦截和查看
通信使用明文传输: 内容可能被窃听
没有验证通信方的身份: 可能会遭到伪装
无法验证报文的完整性: 可能会出现内容被篡改
-
-
-
HTTP/1.1对于效率的优化设计
- 长连接设计: 为了避免每一个数据的请求都创建一个TCP链接, 所以使用长连接的方式进行数据的通信
- 管道传输设计: 为了避免发送端的队头阻塞, 可以在第一个请求还未响应之前发送第二个请求.
- 管道设计的问题: 服务器必须按照接收请求的顺序发送对于管道中请求的响应
- 虽然解决了请求的队头阻塞, 但是没有解决响应的队头阻塞 – 如果服务端响应过慢还是会阻塞后续的请求发送
- 虽然在HTTP1.1上设计了管道通信, 但是没有在实际浏览器中使用
-
-
https和http的差异
- 通过在TCP和HTTP之间添加SSL/TLS安全协议, 使得报文能够进行加密传输
- 相比于Http, HTTPS除了进行TCP的三次握手外还需要完成SSL/TLS的握手过程才进行报文的加密传输
- 两者的端口不同, HTTPS的默认端口为443, HTTP的默认端口是80
- HTTPS需要向证书权威机构申请数字证书, 保证服务器的身份是可信的
- HTTPS解决的三个问题:
- 使用混合加密的方式来实现信息的机密性, 能够解决窃听问题
- 摘要算法实现信息的完整性, 能够通过摘要结果避免信息被篡改
- 服务器公钥存储在数字证书中, 解决了被冒充的风险
- HTTPS的混合加密: 混合加密指的是同时使用对称加密和非对称加密的方式
- 在通讯建立前采用非对称加密方式交换会话秘钥, 在通信过程中使用对称加密的方式加解密文档数据
- Https的摘要算法 + 数字签名: 通过摘要算法计算内容的hash值
- hash值能够保证内容不被篡改, 但是无法保证内容+hash值的整体不会被中间人替换,
- 通过数字签名的方式保证数据不会被中间人替换.
- 数字签名是以公私钥的形式组织的.
- 使用公钥加密, 私钥解密, 能够保证数据传输的安全性
- 使用私钥加密, 公钥解密, 能够保证消息不会被冒充, 因为只要公钥能够正常解出消息, 则证明消息是源于持有私钥身份的人发送的
- 消息签名算法: 对于内容的Hash值, 进行私钥加密, 如果公钥能正常解密则表示该Hash值是原作者的Hash值. 如果消息内容符合Hash值, 表示消息内容未被其他人替换或者篡改
- Https权威认证, 防止公钥被篡改
- 由数字证书认证机构提供自己的数字签名, 和服务器公钥一起打包. 数字证书认证机构的公钥事先存入浏览器或者操作系统中
- 如果用户拿到服务器的公钥后能够通过数字证书认证机构的公钥进行解决, 则可以确认服务器公钥的真实性
- HTTPS建立连接的交互方式:
- 三个大步骤: 客户端向服务器获取服务器公钥, 双方协商生产会话秘钥, 使用会话秘钥进行加密通信
- Https一定安全可靠吗?
- 如果使用中间人转发从客户端到服务端的所有数据包, 理论上可以监控客户端和服务端的所有通信. 但是其前提是客户端中存储了认证中间人的证书.
- 如果中间人不进行HTTPS的解包, 则其效果等效于路由器, 由于无法根据加密的随机数计算会话秘钥, 其无法获取解密内容
- 如果中间人需要对于HTTPS进行解包, 那么中间人和客户端间形成了新的HTTPS链接, 需要校验中间人的HTTPS地址
-
http/1.1, http/2, http/3的演变
-
http/1.1 相对http/1.0的改进:
- 使用长连接改善短连接的开销
- 支持管道进行网络传输
http/1.1的缺陷:
- 响应头部没有经过压缩就进行发送.
- 服务器是按请求顺序进行响应的, 如果服务器响应慢, 会导致队头阻塞
- 没有请求的优先级控制
- 请求只能从客户端开始, 服务器只能进行被动的响应
-
http/2进行的优化:
-
http/2是基于https的,能够保证安全性
-
提供头部压缩能力: 如果多个请求的头是一致的, 其会消除其中的重复部分. 其使用HPACK算法, 在客户端和服务端同时维护一张头信息表, 曾传入的字段会提供一个索引号, 使用索引号优化头字段
-
二进制格式: 使用二进制的方式传输头信息以及数据体, 统称为信息帧. 提高了数据传输的效率
-
并发传输: 提供多个Stream复用同一条TCP链接
一个TCP中包含多个Stream, 一个Stream中可以包含多个Message, 一个Message中存放多个Frame. 每个StreamId是唯一的, 不同的Stream的帧可以乱序发送.
-
服务器推送: 服务器除了可以被动响应客户端消息, 还可以主动向客户端发送消息. 服务端主动建立的Stream的Id为偶数, 由客户端建立的Stream的ID为奇数. 服务器主动推送的效果是对于一些必须的文件, 可以由服务器主动发起请求, 不需要等待用户发起请求.
http/2的问题:
- http/2也具有队头阻塞的问题, 虽然不会再HTTP层面出现队头阻塞问题(可以在同一个TCP中同步传输多个数据). 但是TCP由于要求数据到达的有序性, 所以TCP协议会触发队头阻塞问题. 如果出现TCP包的丢失也会造成整个TCP链接的阻塞
-
-
http/3进行的优化
-
因为基于TCP的http会出现队头阻塞问题, 其在底层将TCP替换为了UDP进行数据传输. 使用QUIC协议替代TCP进行可靠性传输
-
QUIC协议的特点:
-
没有队头阻塞问题:
- 当某个流出现丢包的时候, 只会阻塞该流自身, 不会阻塞其他流
-
可以更快地建立连接
- 对于TCP + TLS协议, 两个协议是分层的, TCP是内核实现的传输层, TLS是openssl实现的表示层. 其需要分批进行握手
- QUIC和TLS不是分层的, 而是在QUIC内部包含TLS协议, 其在QUIC握手的同时可以建立TLS的握手
-
能够实现连接的迁移
-
基于TCP的协议是需要四个参数来描述数据连接: 源IP, 源端口, 目标IP, 目标端口. 但是在移动网络出现网络环境变化时需要断开连接重新建立连接.
由于QUIC协议是通过链接ID进行通信端点的标记, 所以只要保证网络环境变化时连接上下文不发生变化, 就可以无缝地使用原链接.
-
-
-
QUIC协议连接的问题: 因为很多网络设备中没有QUIC网络协议, 只会当做UDP进行处理. 有的网络设备会主动丢弃UDP包. 导致QUIC协议连接推进缓慢
-
-
-
-
HTTP/1.1 如何进行优化
-
优化思路
-
避免发送没必要的HTTP请求
-
对于一些重复性的HTTP请求: 可以将请求-响应数据缓存在本地. 可以直接读取本地数据
使用请求参数令浏览器缓存HTTP请求. 在请求中通过带上Etag进行缓存的校验与获取
-
-
在需要发送HTTP请求时, 考虑减少请求次数
- 减少重定向的次数
- 由于具体存储数据的服务器上的数据可能发生变更, 导致代理服务器多次访问才能获取资源
- 将资源的重定向信息放在代理服务器上, 将重定向的URL放在代理服务器上. 能够通过本地缓存避免多次访问
- 合并请求
- 对于多个频繁一起访问的小文件可以合并为一个大的请求. 通过减少请求的数量减少请求头的传输性能消耗
- 例如可以将图标文件合并为一个大图片, 在浏览器上对于图片进行分割. 可以将图片以base64形式进行编码后嵌入到HTML文件中, 直接跟随HTML一起发送
- 合并请求的问题: 当被合并的请求中有一个小资源发生更新后, 会需要客户端更新整个大资源包
- 延迟发送请求
- 使用懒加载的方式, 对于不一定需要的资源不进行加载. 当用户向下滑动页面的时候, 再向服务器获取接下来的资源
- 减少重定向的次数
-
减少服务器的HTTP响应的数据大小
- 使用无损压缩响应数据
- 例如使用 gzip, Brotli 进行数据的压缩
- 使用有损压缩响应数据
- 例如图片, 音频, 视频等多媒体数据, 可以通过在Accept中的q质量因子控制获取的目标资源质量
- 使用无损压缩响应数据
-
-
-
HTTPS RSA 握手解析