计算机网络

第一章 概述

1.1 信息时代的计算机网络

1.1.1 计算机网络的各类应用

CN_20250518_000006

CN_20250518_000007

1.1.2 计算机网络带来的负面影响

CN_20250518_000008

1.2 因特网概述

1.2.1 网络,互连网(互联网)与因特网

网络[1]: 由若干 结点链路 互连形成

互联网[2]:(internet)网络[1:1]通过路由器[3]互连形成,互联网是"网络的网络"

因特网[4]: (Internet)是当今世界上最大的互联网

1.2.2 因特网发展的三个阶段

  1. 从单个网络 ARPANET[5] 向互联网发展
  2. 逐步建成三级结果的因特网
    1. NSF 建设 NSFNET[6](主干网,地区网和校园网)
  3. 逐步形成了多层次ISP结果的因特网

第一层 ISP[7] 通常被称为因特网主干网,一般都能够覆盖国际性区域范围,并拥有高速链路和交换设备。第一层 ISP 之间直接相连
第二层 ISP 和一些大公司都是第一层 ISP 的用户,通常具有区域性或国家性覆盖,与少数第一层 ISP 相连接
第三层 ISP 又称为本地 ISP ,它们是第二层 ISP 的用户且只拥有本地范围的网络,如一般的校园网企业网,以及住宅用户和无线移动用户,都是第三层 ISP 的用户

1.2.3 因特网的标准化工作

因特网在制定标准上的一个很大的特点是 面向公众
因特网所有的 RFC[8] 技术文档都可从因特网免费下载(http://www.ietf.org/rfc.html)

ISOC[9] 是一个国际性组织,它负责对因特网进行全面管理,以及在世界范围内促进其发展和使用

1.2.4 因特网的组成

  1. 边缘部分
    由所有连接在因特网上的 主机 组成。这部分是 用户直接使用 的,用来进行 通信 (传送数据,音频或视频)和 资源共享
  2. 核心部分
    大量网络 和连接这些网络的路由器组成。这部分是 为边缘部分提供服务 的(提供连通性和交换)

1.3 三种交换方式:电路交换,分组交换和报文交换

  1. 电路交换
    1. 电话交换机接通电话线的方式称为电路交换
    2. 从通信资源的分配角度看,交换就是按照某种方式动态地分配传输线路的资源
    3. 电路交换的三个步骤:
      1. 建立连接(分配通信资源)
      2. 通话(一直占用通信资源)
      3. 释放连接(归还通信资源)
  2. 分组交换
    1. 发送方:构造分组,发送分组
    2. 路由器:缓存分组,转发分组
    3. 接收方:接受分组,还原报文
  3. 报文交换

CN_20250605_010249

  1. 电路交换
    1. 优点:
      1. 通信时延小
      2. 有序传输(数据不会失序)
      3. 没有冲突(不会争用物理信道)
      4. 适用范围广(模拟信号和数字信号都能)
      5. 实时性强
      6. 控制简单
    2. 缺点:
      1. 建立连接时间长
      2. 线路独占,使用效率低
      3. 灵活性差
      4. 难以规格化
  2. 报文交换
    1. 优点:
      1. 无需建立连接
      2. 动态分配线路
      3. 提高线路可靠性
      4. 提高线路利用率
      5. 提供多目标服务
    2. 缺点:
      1. 引起了转发时延
      2. 需要较大的存储缓存空间
      3. 需要传输额外信息量
  3. 分组交换
    1. 优点:
      1. 无需建立连接
      2. 线路利用率高
      3. 简化了存储管理
      4. 加速传输
      5. 减少出错概率和重发数据量
    2. 缺点:
      1. 引起了转发时延
      2. 需要传输额外信息量
      3. 对于数据报服务,存在失序、丢失或重复分组的问题;对于虚电路服务,存在呼叫建立、数据传输和虚电路释放三个过程

第四章 网络层

4.3 IPv4 地址

4.3.1 IPv4 地址概述

IPv4地址[10] 就是给因特网[4:1]上的 每一台主机(或路由器)的每一个接口 分配一个在全世界范围内是 唯一的32比特的标识符

IPv4地址的编址方法经历了如下三个历史阶段

  1. 分类编址
  2. 划分子网
  3. 无分类编址

32比特的 IPv4地址不方便阅读,记录以及输入等,因此 IPv4地址采用 点分十进制表示方法[11]以方便用户使用

4.3.2 分类编址的IPv4地址

种类 固定前缀 网络号位数 主机号位数 功能
A 0 8 24
B 10 16 16
C 110 24 8
D 1110 - - 多播地址
E 1111 - - 保留为今后使用

只有ABC类地址可分配给网络中的主机或路由器的各接口
网络地址[12]和广播地址[13]不能分配给主机或路由器的各接口

A类地址,B类地址和C类地址

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

  • 最小的本地环回测试地址为127.0.0.1
  • 最大的本地环回测试地址为127.255.255.254
    可指派的网络数量为 \(2^8 - 2 = 126\)
    每个网络中可分配的 IP 地址数量为 \(2^{24} - 2 = 16777214\)
种类 最小网络号 最小可指派网络号 最大可指派网络号 最大网络号 可指派的网络数 网络中可分配的IP数
A 0 1 126 127 \(2^{8-1}-2=126\) \(2^{24} - 2 = 16777214\)
B 128.0 128.0 191.255 191.255 \(2^{16-2}=16384\) \(2^{16} - 2 = 65534\)
C 192.0.0 192.0.0 223.255.255 223.255.255 \(2^{24-3}=2097152\) \(2^{8} - 2 = 254\)

4.3.3 划分子网的IPv4地址

  1. 32 比特的子网掩码可以表明分类IP地址的主机号部分被借用了几个比特作为子网号
  2. 子网掩码使用 连续的比特0来对应主机号
  3. 将划分子网的 IPv4地址 与其相应的 子网掩码 进行 逻辑与运算 就可得到 IPv4地址 所在的网络地址

默认的子网掩码是指在未划分子网的情况下使用的子网掩码

A类网络: 255.0.0.0
B类网络: 255.255.0.0
C类网络: 255.255.255.0

4.3.4 无分类编址的IPv4地址

划分子网在一定程度上缓解了因特网在发展中遇到的困难,但是数量巨大的C类网因为其地址空间太小并没有得到充分使用,而因特网的IP地址仍在加速消耗,整个IPv4地址空间面临全部耗尽的威胁

CIDR

为此 IEFT[15]提出了采用 无分类编址 的方法来解决,同时成立IPv6工作组

1993年,IEFT[15:1]发布了 无分类域间路由选择CIDR[16]

  1. CIDR[16:1] 消除了传统的A类,B类和C类地址,以及划分子网的概念
  2. CIDR[16:2] 可以更加有效的分配IPv4的地址空间,并且可以在新的IPv6使用之前允许因特网的规模继续增长

CIDR[16:3] 使用“斜线记法”,或称 CIDR 记法。即在IPv4的地址后面加上斜线"/",在 斜线后面写上网络前缀所占的比特数量

例子 128.14.35.7/20
网络前缀占用的比特数量: 20
主机号占用的比特数量: 32 - 20 = 12

CIDR实际上是 将网络前缀都相同的连续的IP地址组成一个"CIDR地址块"
我们只要知道 CIDR 地址块中的任何一个地址,就可以知道改地址块的全部细节:

  1. 地址块的最小地址
  2. 地址块的最大地址
  3. 地址块中的地址数量
  4. 地址块聚合某类网络(A类,B类或C类)的数量
  5. 地址掩码(也可以继续称为子网掩码)
例子:

给出 128.14.35.7/20的全部细节(最小地址,最大地址,地址数量,聚合C类网,地址掩码)

  1. 最小地址: 128.14.32.0
  2. 最大地址: 128.14.47.255
  3. 地址数量: \(2^{(32 - 20)}\)
  4. 聚合C类网的数量 \(2^{(32 - 20)} / 2^8\)
  5. 地址掩码(也可以继续称为子网掩码): 11111111.11111111.11110000.00000000 = 255.255.240.0
路由聚合

一个路由器将与自己直接相连的局域网的信息通告给另一路由器时,会构造聚合地址块[17]来通告

网络前缀越长,地址块越小,路由越具体

若路由器查表转发分组时发现有多条路由可选,则选择网络前缀最长的那条,这称为 最长前缀匹配 ,因为这样的路由更具体

4.3.5 IPv4 地址的应用规划

定长的子网掩码 变长的子网掩码
使用同一个子网掩码来划分子网 使用不同的子网掩码来划分子网
每个子网所分配的IP地址数量相同,造成IP地址的浪费 每个子网所分配的IP地址数量可以不同,尽可能减少对IP地址的浪费

网络的IP地址需求 = 主机地址 + 路由器接口地址 + 网络地址 + 广播地址

\[地址 \begin{cases} 网络地址 \\ 可分配地址 \begin{cases} 路由器接口地址 \\ 主机地址 \end{cases} \\ 广播地址 \end{cases} \]

分配IP地址

分配网络前缀时需要预留特定地址:网络地址[12:1],广播地址[13:1], 路由器接口地址[18]

代码实现分配IP地址

输入格式

第一行是该系统分配到的地址块
第二行是该系统内的局域网数 \(n\)
下面 \(n\) 行是每个局域网的主机数,以及与该局域网直接相连的路由器的数量

代码

该代码实现了对输入分配给系统的IP地址块以及各局域网的主机数以及直接相连的路由器数,自动按照优先分配占用地址多的局域网,优先分配位上数为0的规则,分配每一个局域网包括前缀的地址块的功能

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// 点分十进制的段数
constexpr int m = 4;
// 每一段的位数
constexpr int k = 8;
constexpr int pn = 62;
ll p[pn + 1];
// 初始化 2 的幂次
void initp() {
    p[0] = 1;
    for (int i = 1; i <= pn; ++ i) p[i] = p[i - 1] * 2ll;
}
// 求出不小于 x 的最小的 2 的幂次(二分算法) 
// O(log_2(x)) 对于输入的局域网数 n 该算法为O(1)
ll higherbit(ll x) {
    ll l = 2, r = m * k;
    while (l <= r) {
        ll mid = (l + r) >> 1;
        // 减 2 是因为全 0 是网络地址,全 1 是广播地址需要预留
        if ((1ll << mid) - 2 < x) {
            l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    return (1ll << l);
}
// 化为点分十进制
string f(ll ip) {
    string res = "";
    vector<ll> a(m + 1);
    for (int i = m; i >= 1; -- i) {
        a[i] = ip % (1 << k);
        ip >>= k;
    }
    for (int i = 1; i <= m; ++ i) {
        if (res.size()) res += '.';
        res += to_string(a[i]);
    }
    return res;
}
int main() {
    cin.tie(nullptr)->sync_with_stdio(false);

    initp();

    ll prefix, ip = 0, n;
    char c;
    vector<ll> t(m + 1);
    for (int i = 1; i <= m; ++ i) {
        cin >> t[i] >> c;
        ip <<= k;
        ip += t[i];
    }
    cin >> prefix;
    cin >> n;
    vector<ll> LAN(n + 1); // 每个局域网中主机的数量
    vector<ll> routers(n + 1); // 每个局域网直接相连的路由器的数量
    vector<string> ans(n + 1); // 每个局域网对应的网络前缀
    vector<tuple<ll, ll, int, int>> tl;
    vector<ll> IP(n + 1);
    vector<string> pre(n + 1);
    for (int i = 1; i <= n; ++ i) cin >> LAN[i] >> routers[i];
    for (int i = 1; i <= n; ++ i) {
        tl.emplace_back(
            higherbit(LAN[i] + routers[i]), 
            LAN[i] + routers[i], 
            -i,
            i
        );
    }
    // 按局域网内的主机数降序排序
    sort(tl.rbegin(), tl.rend());
    for (auto [num, rnum, _id, id] : tl) {
        // 计算地址块
        string cur = f(ip);
        // 计算前缀
        int cn = prefix;
        while (num < p[m * k - cn]) cn++;
        // 合并成答案
        ans[id] = cur + "/" + to_string(cn);
        // 存储当前IP和前缀用于后续验证答案
        IP[id] = ip;
        pre[id] = cn;
        // 模拟占用这些地址号
        ip += num;
    }   
    for (int i = 1; i <= n; ++ i) {
        cout << "LAN" << i << ": " << ans[i] << "\n";
    }
    auto show = [&](int id) {
        ll x = IP[id];
        vector<int> c(m * k);
        for (int i = m * k; i >= 1; -- i) {
            c[i] = x & 1;
            x >>= 1;
        }
        for (int i = 1; i <= m * k; ++ i) {
            cout << c[i];
            if (i % k == 0) {
                if (i < m * k) cout << ".";
                else cout << "\n";
            }
        }
    };
    // 输出二进制形式,人工手动验证答案
    // for (int i = 1; i <= n; ++ i) {
    //     cout << "LAN" << i << ":\n";
    //     show(i);
    // }
}

4.4

联系我

博客失去时效性或有任何不详尽的可联系我

QQ: 2832640093


  1. 网络 由若干 结点链路 互连形成 ↩︎ ↩︎ ↩︎

  2. 互联网 若干网络[1:2] 通过路由器互连形成 ↩︎

  3. 路由器 NEED ↩︎

  4. 因特网 是当今世界上最大的互联网 ↩︎ ↩︎ ↩︎

  5. ARPANET 第一个分组交换网 ↩︎

  6. NSFNET 国家科学基金网 ↩︎

  7. ISP (internet service provider)互联网服务提供商 ↩︎

  8. RFC Request For Comments ↩︎ ↩︎

  9. ISOC 因特网协会,是一个国际性组织,它负责对因特网进行全面管理,以及在世界范围内促进其发展和使用 ↩︎

  10. IPv4地址 就是给因特网[4:2]上的 每一台主机(或路由器)的每一个接口 分配一个在全世界范围内是 唯一的32比特的标识符 ↩︎

  11. 点分十进制表示方法 每8位分为一组,写出每组的十进制数,每个十进制之间用"."来分隔 ↩︎

  12. 网络地址 主机号为“全0”的地址 ↩︎ ↩︎

  13. 广播地址 主机号为“全1”的地址 ↩︎ ↩︎

  14. 本地环回测试地址 NEED ↩︎

  15. IEFT 因特网工程任务组 ↩︎ ↩︎

  16. CIDR classless Inter-Domain Routing 的RFC[8:1]文档 ↩︎ ↩︎ ↩︎ ↩︎

  17. 聚合地址块 将与该路由器直接相连的局域网的的IP取共同前缀其他位变0后生成的地址块 ↩︎

  18. 路由器接口地址 每个路由器的接口需要预留独立的IP地址 ↩︎

posted @ 2025-05-09 00:28  Proaes  阅读(23)  评论(0)    收藏  举报