网络层

湖科大计网

分类编址的IPv4地址

A类地址

最小网络号为0, 保留不指派
第一个可指派的网络号为1, 网络地址为1.0.0.0
最大网络号为127, 作为本地环回测试地址,不指派

  • 最小的本地环回测试地址为127.0.0.1
  • 最大的本地环回测试地址为127.255.255.254
    最后一个可指派的网络号为126

可指派的网络的数量为126, 每个网络中可以分配的IP地址数量为2^24 - 2 = 16777214 (减2是取出全0的网络地址和全1的广播地址)

B类

最小网络号128, 最大网络号191.255
可指派网络数为2 ^ (16 - 2) = 16384, 每个网络中可分配的IP地址数量为2 ^ 16 - 2 = 65534

C类

最小网络号192, 最大网络号223.255.255
可指派的C类网络数量2 ^(24 - 3), 每个网络中可分配的IP地址数量为2 ^ 8 - 2

划分子网的IPv4地址

为了减少IP的浪费,把一个大的IP地址切分为多个小的子网

结构变为<网络号><子网号><主机号>

无分类编址的IPv4地址

即使有了划分子网,但是还不够彻底,仍然有巨大的浪费

Classless Inter-Domain Routing (无分类域间路由)CIDR 使用斜线记法,可以在 IP 后面直接写 /n,表示前 n 位是网络前缀

路由聚合(构造超网)

将多个较小的子网和1并成一个较大的网络
网络前缀越长,路由越具体,如果路由器查表转发分组的时候发现有多条路由可以选择,则选择网络前缀最长的那个,这样的路由更具体

IPv4地址的应用规划

采用 VLSM (可变长子网掩码),根据实际的主机数量,按需分配

IP数据报的发送和转发过程

主机A给B发送数据,先将自己的IP地址与子网掩码进行运算,得出自己的网络号。然后将目标IP地址与子网掩码运算,得到目标地址的网络号,如果相同,说明在同一个子网内,主机A直接发送给B。如果不同,说明不在同一个子网内,主机A将数据发送给默认网关(通常是路由器),路由器拿着目的IP地址与自己路由表里的条目逐条匹配,如果找到,就将数据发送

匹配算法

  • 用路由表中每一行的掩码目标 IP (D) 做 AND 运算。

  • 如果结果等于该行的目的网络地址,则匹配成功。

  • 如果有多行匹配成功,选择掩码最长(最精确)的那一行。

  • 如果没有一行匹配,丢弃数据报,向源主机报错(ICMP 目的不可达)

静态路由配置及其可能产生的路由环路问题

  1. 互指的错误
  2. 路由汇总 + 错误聚合
    针对情况2,使用黑洞路由解决。
    如果路由器查表的时候有多条能够匹配,使用最精确的那一条
  • 正常流量 (如 192.168.1.1):

    • 路由器上有具体的明细路由(比如是通过动态路由学到的,或者是直连的)。

    • 明细路由 /24 比 Null0 的汇总路由 /16 更长。

    • 结果: 正常转发,不会被丢弃。

  • 异常流量 (如 192.168.3.1):

    • 路由器上没有 .3.0 的明细路由。

    • 此时,它匹配到了我们刚写的 192.168.0.0/16 -> Null0

    • 虽然可能还有默认路由指向外网,但 /16/0 (默认路由) 长。

    • 结果: 路由器直接把包扔进垃圾桶 (Null0)。环路被切断了!

路由选择协议


image.png

RIP的基本工作原理

image.png

更新过程

image.png

  1. 路由器B收到了路由器A的路由表
  2. 改造信息: B收到了A的路由表后, 把所有的举例都加1, 下一跳都改为A(B是A的相邻表,距离加1跳)
    更新原则:
    • 新路线: A知道网络X怎么去,距离是x, B不知道, 直接添加
    • 更短路线: A到网络Y要2跳,B到Y原本走C要5跳,更新,以后到Y走A
    • 同源更新: A到网络Z需要10, B原本就是走A到Z的只需要3跳, 更新
    • 更差的路线: 不管
RIP的缺点:坏消息传的慢(慢收敛)
  1. 路由器 A 连着网络 N,A 告诉 B:“去 N 只要 1 跳”。

  2. B 告诉 C:“去 N 只要 2 跳”。

  3. 突然,A 和 N 断了。A 将去 N 的距离改为 16(不可达)。

  4. 但在 A 的更新包发给 B 之前,B 抢先给了 A 一个更新:“嘿,去 N 走我这里只要 2 跳哦!”(这是 B 之前从 A 那里听来的旧闻)。

  5. A 傻了:“哦?你能去 N?那我把数据给你,距离变成 3。”

  6. A 和 B 开始互相欺骗,距离从 3 涨到 4,4 涨到 5… 直到涨到 16。

  7. 这就是 “计数到无穷” (Count-to-Infinity) 问题,形成了路由环路。
    image.png

OSPF的基本工作原理

  • OSPF是基于链路状态的,而不是像RIP一样基于距离向量
  • 采用Dijkstra提出的最短路径算法SPF计算路由, 从算法上保证了不会产生路由环路
  • 不限制网络规模, 更新效率高,收敛速度块
  • 链路状态是指本路由器和哪些路由器相邻以及相映链路的“代价“
工作流程
  1. 建立邻居关系
    相邻路由器通过交互问候(hello)分组, 建立和维护邻居关系
    • 动作: 只要两个路由器互相收到了对方的 Hello 包,它们就建立了邻居关系 (Neighbor Relationship)

    • 目的: 确认链路是通的,并确立“我们俩要开始交换信息了”。

    • 维持: 之后也会周期性发送 Hello 包(通常 10秒一次)作为“心跳”,如果 40秒(Dead Time)没收到邻居的 Hello,就认为邻居挂了。

  2. 链路状态洪泛
    使用OSPF的路由器会产生链路状态通告(LSA), LSA中包含直连网络的状态信息, 相邻路由器的链路状态信息,与相邻路由器间的”代价“
    • 泛洪 (Flooding): 每个路由器都会把自己的 LSA 发给邻居,邻居收到后,原封不动地拷贝一份发给它的邻居。

    • 结果: 就像连锁反应一样,最终全网所有的路由器都收到了每一台路由器的 LSA。

  3. 构建链路状态数据库(LSDB)
    将收集到的LSA存到数据库中
  4. 计算最短路径
    有了LSDB,路由器开始运行 Dijkstra 算法,构建出到达其他各路由的最短路径, 即构建路由表
区域

如果网络特别大, LSDB会变得巨大, 为了使SPF可以用于大规模的网络,OSPF把一个自治系统划分为若干小范围的系统,叫做区域
image.png

边界网关协议BGP

image.png
BGP 是目前互联网上唯一使用的 EGP (外部网关协议)。它的核心任务不是“找最快的路”,而是**“找一条能走、且符合策略(Policy)的路”**
image.png

IPv4数据报的首部格式

网际控制报文协议ICMP

  1. 终点不可达
  2. 源点抑制
    路由器或主机由于拥塞而丢弃数据时,向源点发送源点抑制报文,使源点知道应当把数据报的发送速率减缓
  3. 时间超过
  4. 参数问题
  5. 改变路由(重定向)
以下情况不发送ICMP
  • 对ICMP差错报告报文不发送ICMP差错报告报文
  • 对第一个分片的数据报片的所有后续数据报片不发送ICMP差错报告报文
  • 对具有多播地址的数据报都不发送ICMP差错报告报文
  • 对具有特殊地址(如127.0.0.1或0.0.0.0)的数据报不发送
常见的ICMP询问报文
  • 回送请求和回答
    由主机或路由器向一个特定的目的主机发出的询问,收到此报文的主机必须给源主机或路由器发送ICMP回送回答报文。
    这种报文用于测试目的站是否可达
  • 时间戳请求和回答
    请某个主机或路由器回答当前的日期和时间
    进行时间同步和测量时间
ICMP应用
  • ping
  • traceroute

虚拟专用网VPN与网络地址转换NAT

image.png

运输层

UDP与TCP对比

UDP(user datagram protocal) tcp(transmission control protocal)
UDP

  • 无连接
  • 支持一对一, 一对多,多对多,多对一交互通信
  • 对应用层交付的报文直接打包
  • 尽最大努力交付,不可靠,不使用流量控制和拥塞控制
  • 首部开销小,只有8个字节
    TCP
  • 面向连接
  • 只能一对一传输
  • 面向字节流
  • 可靠传输,使用流量控制拥塞控制
  • 首部最小20字节,最大60字节

TCP的流量控制

如果发送方发送数据过快,接收方可能来不及接受,这回导致数据的丢失。
流量控制就是让发送方的速率不要太快,让接收方来的及接收
利用滑动窗口机制可以在TCP上实现对发送方的流量控制

滑动窗口
  • 接收方每次发送确认报文的时候,都会在窗口字段填入当前自己的缓冲区还有多少空间
  • 发送方收到ACK后,更新自己的发送窗口,保证已经发送但未收到确认的数据量<=接收方的通知窗口大小
  • 接收方读取了缓冲区的数据,有更多的空间,会发送一个新的ACK告诉发送方,发送方的窗口向右滑动,继续发送
窗口关闭

如果接收方缓冲区已经满了,会发送一个窗口为0的报文,此时发送方停止发送
但是这又有一个新的问题,如果接收方处理了数据,有空余的空间,发送一个窗口增加的报文,但是这个报文在网络中丢失了,怎么办? 这会导致死锁
解决方案:窗口关闭时,发送方启动一个定时器,周期性的向接收方发送一个字节数的探测报文,接收方收到后必须回复当前窗口的大小,这样就不会死锁

TCP的拥塞控制

image.png

拥塞控制是一个不断试探网络的过程,一旦发现丢包,就立即减少发送量,然后再慢慢增加

关键变量:cwnd (拥塞窗口)ssthresh (慢启动阈值)

cwnd: 发送方可以发送的数据量,不考虑接受方能不能接受
ssthresh:是慢启动与拥塞避免阶段的分界

  1. 慢启动
    刚开始建立连接时,不知道网络状况什么样,从极小的大小开始试探
    初始cwnd=1,发送数据,每收到一个ACK就+1
    每次窗口都翻倍增长
    当cwnd增长到>=ssthresh时,慢启动结束,进入拥塞避免阶段

  2. 拥塞避免
    不再翻倍增长,而是每经过一个发送确认周期,cwnd大小只增加1
    直到网络出现丢包结束

  3. 拥塞发生

    1. 严重拥塞
      发送方迟迟收不到 ACK,直到定时器(RTO)超时。TCP 认为网络可能瘫痪了,反应非常剧烈。
      ssthresh设置为当前cwnd的一半,然后将cwnd大小重置为1,重新进入慢启动阶段
    2. 轻微拥塞
      发送方收到了连续3个重复的ACK(这说明中间有包丢失了,但是后面的都收到了),TCP认为网络还行,不需要重置为1,进行快重传,快恢复
      • ssthresh设置为cwnd的一半
      • 将cwnd设置为ssthresh + 3(3是那三个重复的ACK)
      • 进入快恢复
  4. 快恢复

    • 如果继续收到重复的 ACK,说明还有后续数据包到达了(都在网络里),cwnd 继续 +1

    • 直到收到新的 ACK(确认了重传的数据包),说明丢包已经补上了。

    • 退出快恢复:将 cwnd 设置为 ssthresh(即刚才减半后的值),然后进入拥塞避免阶段(线性增长)。

image.png

image.png

TCP超时重传

TCP 超时重传时间 (RTO, Retransmission TimeOut)
RTT:数据包从发送到收到ACK的往返时间
如果RTO设置的时间太短,没有丢包也会认为丢包,产生不必要的重传,如果设置的时间太长,真发生丢包的时候,重传太慢,效率也很低

TCP采用动态算法计算RTO,让RTO的时间略大与RTT

image.png

image.png

TCP的连接建立

三次握手
image.png

  • 最初都处于close状态
  • TCP服务器进程首先创建传输控制快,然后等待TCP客户端的连接请求,进入监听状态,
  • 客户端随机生成一个初始序列号 xx。发送报文。报文内容: SYN=1, seq=x
  • 服务器收到请求,同意建立连接。它需要确认客户端的 xx,同时自己也生成一个初始序列号 yy报文内容: SYN=1, ACK=1, seq=y, ack=x+1
  • 客户端收到服务器的同意。需要对服务器的 yy 进行确认。报文内容: ACK=1, seq=x+1, ack=y+1
    • 客户端发送后,进入 ESTABLISHED (已建立连接) 状态。
    • 服务器收到后,也进入 ESTABLISHED 状态
      为什么必须是“三次”,两次行不行?
      防止“已失效的连接请求”突然到达
  1. 客户端发了第一个请求(A),但在网络里滞留了

  2. 客户端看 A 没回复,以为丢了,又发了一个请求(B)。

  3. B 顺利完成了连接、传输、断开。

  4. 过了一会儿,滞留的 A 终于到了服务器。

  • 如果是两次握手: 服务器收到 A,以为客户端又要建新连接,立刻回复“好的”,连接就建立了。服务器开始傻等客户端发数据,浪费资源。

  • 如果是三次握手: 服务器收到 A,回复“好的”(第二次握手)。客户端收到后,发现:“咦?我没想建连接啊,这是旧消息。”于是客户端拒绝发送第三次确认。服务器收不到确认,就知道连接建立失败,释放资源。

第三次握手是可以携带数据的,前两次握手是不可以携带数据的

TCP连接关闭

image.png