习题HJ18 IP地址与子网掩码

本文介绍了IP地址的不同类型(A类、B类、C类、D类、E类),子网掩码的作用,以及如何通过子网掩码划分和统计IP地址。特别强调了C类地址的子网划分实例,以及公网与私网IP的区别。此外,还提供了代码示例来处理有效IP地址和子网掩码的检查与统计。

习题HJ18 识别有效的IP地址和掩码并进行分类统计及相关知识复习

1. IP地址与子网掩码

  IP地址作为计算机在网络内的唯一标识,由网络地址 + 主机地址组成。子网掩码将某个IP地址划分成网络地址和主机地址两部分。

1.1 IP地址分类

1.1.1 地址类型分类

 地址类型   十进制地址范围   特征   A类地址  1.0.0.0 − 127.255.255.255  第1个8位中的第1位始终为  0  B类地址  128.0.0.0 − 191.255.255.255  第1个8位中的第1、2位始终为  10  C类地址  192.0.0.0 − 223.255.255.255  第1个8位中的第1、2、3位始终为110   D类地址  224.0.0.0 − 239.255.255.255  第1个8位中的第1、2、3、4位始终为1110   E类地址  240.0.0.0 − 247.255.255.255  第1个8位中的第1、2、3、4、5位始终为11110  \begin{array}{|c|c|c|} \hline \text { 地址类型 } & \text { 十进制地址范围 } & \text { 特征 } \\ \hline \text { A类地址 } & 1.0 .0 .0-127.255 .255 .255 & \text { 第1个8位中的第1位始终为 } 0 \\ \hline \text { B类地址 } & 128.0 .0 .0-191.255 .255 .255 & \text { 第1个8位中的第1、2位始终为 } 10 \\ \hline \text { C类地址 } & 192.0 .0 .0-223.255 .255 .255 & \text { 第1个8位中的第1、2、3位始终为110 } \\ \hline \text { D类地址 } & 224.0 .0 .0-239.255 .255 .255 & \text { 第1个8位中的第1、2、3、4位始终为1110 } \\ \hline \text { E类地址 } & 240.0 .0 .0-247.255 .255 .255 & \text { 第1个8位中的第1、2、3、4、5位始终为11110 } \\ \hline \end{array}  地址类型  A类地址  B类地址  C类地址  D类地址  E类地址  十进制地址范围 1.0.0.0127.255.255.255128.0.0.0191.255.255.255192.0.0.0223.255.255.255224.0.0.0239.255.255.255240.0.0.0247.255.255.255 特征  18位中的第1位始终为 0 18位中的第12位始终为 10 18位中的第123位始终为110  18位中的第1234位始终为1110  18位中的第12345位始终为11110 

注意:【0.*.*.*】和【127.*.*.*】是本地回环地址( 计算机以回环地址发送的消息,并不会由链路层送走,而是被本机网络层捕获。用处只有一个,就是自己发给自己,自娱自乐),不属于上述任意一类,也不属于不合法IP地址。

  现有一个C类地址的IP地址段192.168.1.0~192.168.1.225(共256个IP地址),想要把这个IP地址段划分成四个子网网段(每个子网64个IP地址),使得主机直接无法跨子网通信:

192.168.1.0-192.168.1.63
192.168.1.64-192.168.1.127
192.168.1.128 -192.168.1.191
192.168.1.192-192.168.1.255

如何去直接描述这四个IP子网段?

解决方法:子网掩码

1.1.2 地址范围分类

  由于我国接入国际互联网的时期比较晚,所以分配到的IPv4地址十分的稀少,IP地址的供应更是严重不足。为了应对这个问题,IPv4地址被划分为公网IP和私网IP。
  私网IP只能在组织机构内部使用,不会出现在互联网上的,无法直接使用它们来访问互联网,而只能在本地连接也就是局域网中使用。公网IP能直接连接上网络,所以对于那些住宅小区,公司,学校,政府机构等场所,就可以集中使用私有的IP进行管理,而大家可以共用一个IP去连接上公网,这样,就省下了许多宝贵的公网IP。

私网IP范围是:
从10.0.0.0到10.255.255.255
从172.16.0.0到172.31.255.255
从192.168.0.0到192.168.255.255

这也是每次使用ipconfig查到的地址,要么就是172.开头的,要么就是192.开头的(是学生的话基本就是10.开头)。ipconfig查询到的其实只是我们的局域网IP,172.开头的意味着我们是B类型的局域网,以192.开头的意味着你是c类的局域网。所以我们一直都没有接触到正真的IP,我们一直打交道的都是私网IP。

1.2 子网掩码

  子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。

192.168.1.0-192.168.1.63

  以第一个子网段为例,其二进制共有26位首尾地址完全相同。所以子网掩码为255.255.255.192,其中共有26个1,该子网可以缩写为/26。所以说第一个子网段可以用网段192.168.1.0/26表示。注意一个子网中主机号全为0的是网络地址,全为1的是广播地址,这两个地址无法作为主机地址。

广播地址 = (~子网掩码) | 网络地址

 十进制地址   二进制情况 192.168.1.0 11000000.10101000.00000001.00000000 192.168.1.63 11000000.10101000.00000001.00111111 255.255.255.192 11111111.11111111.11111111.11000000 \begin{array}{|c|c|c|} \hline \text { 十进制地址 } & \text { 二进制情况} \\ \hline 192.168.1.0& 11000000.10101000.00000001.00000000 \\ \hline 192.168.1.63 & 11000000.10101000.00000001.00111111 \\ \hline 255.255.255.192 & 11111111.11111111.11111111.11000000 \\ \end{array}  十进制地址 192.168.1.0192.168.1.63255.255.255.192 二进制情况11000000.10101000.00000001.0000000011000000.10101000.00000001.0011111111111111.11111111.11111111.11000000

 默认子网掩码   网络类型   默认子网掩码   缩写   A类地址  255.0.0.0 / 8  B类地址  255.255.0.0 / 16  C类地址  255.255.255.0 / 24 \begin{aligned} &\text { 默认子网掩码 }\\ &\begin{array}{|c|c|c|} \hline \text { 网络类型 } & \text { 默认子网掩码 } & \text { 缩写 } \\ \hline \text { A类地址 } & 255.0 .0 .0 & /8 \\ \hline \text { B类地址 } & 255.255 .0 .0 & /16 \\ \hline \text { C类地址 } & 255.255 .255 .0 & /24 \\ \hline \end{array} \end{aligned}  默认子网掩码  网络类型  A类地址  B类地址  C类地址  默认子网掩码 255.0.0.0255.255.0.0255.255.255.0 缩写 /8/16/24

1.3 能否通信要看网络地址

网络地址 = IP & 子网掩码

  一个主机192.168.1.199/26 能否和直连主机192.168.1.200/24 通信?能否和直连主机 192.168.1.1/24 通信?PS: 显然/24就是子网掩码255.255.255.0的缩写

192.168.1.199/26的网络地址为192.168.1.192,即

11000000.10101000.00000001.11000111 &
11111111.11111111.11111111.11000000

192.168.1.200/24的网络地址为192.168.1.192
192.168.1.1/24的网络地址为192.168.1.0
显然,(1)能,(2)否,实现了主机直接无法跨子网通信

1.4 子网容量

子网数量:子网掩码包含了网络地址的信息,除去被网络地址占用的bit位,剩余bit位将用作主机地址。

子网数 = 2^(实际子网掩码缩写 - 相应网络类型默认子网掩码缩写)
在上述案例中,2^(26-24) = 4,即将一个C类IP地址段划分为了四个子网。

最大主机数

计算方式:最大主机数 = 2^(主机地址的位数)

可用主机数

计算方式:可用主机数 = 最大主机数 - 2
因为一个子网中主机号全为0的是网络地址,全为1的是广播地址,所以要 -2

2. 习题HJ18 识别有效的IP地址和掩码并进行分类统计

题目链接
思路:

  1. 按行读取输入,根据字符‘~’ 将IP地址ip与子网掩码mask分开
  2. 检查是否为私有IP地址,是的话则跳过后续检测进行下一行的读入
  3. 查看子网掩码是否合法。
    合法,则继续检查IP地址
    非法,则相应统计项+1,继续下一行的读入
  4. 查看IP地址是否合法
    合法,查看IP地址属于哪一类,是否是私有ip地址;相应统计项+1
    非法,相应统计项+1
#include<iostream>
#include<string>
#include<sstream>
#include<vector>
using namespace std;

bool judge_ip(string ip) {
    int j = 0;
    istringstream iss(ip);
    string seg;
    while (getline(iss, seg, '.'))
        if (++j > 4 || seg.empty() || stoi(seg) > 255)
            return false;
    return j == 4;
}

bool is_private(string ip) {
    istringstream iss(ip);
    string seg;
    vector<int> v;
    while (getline(iss, seg, '.')) v.push_back(stoi(seg));
    if (v[0] == 10) return true;
    if (v[0] == 172 && (v[1] >= 16 && v[1] <= 31)) return true;
    if (v[0] == 192 && v[1] == 168) return true;
    return false;
}

bool is_mask(string ip) {
    istringstream iss(ip);
    string seg;
    unsigned b = 0;
    while (getline(iss, seg, '.')) b = (b << 8) + stoi(seg);
    if (!b) return false;
    b = ~b + 1;
    if (b == 1) return false;
    if ((b & (b - 1)) == 0) return true;
    return false;
}

int main() {
    string input;
    int a = 0, b = 0, c = 0, d = 0, e = 0, err = 0, p = 0;
    while (cin >> input) {
        istringstream is(input);
        string add;
        vector<string> v;
        while (getline(is, add, '~')) v.push_back(add);
        int first = stoi(v[0].substr(0, v[0].find_first_of('.')));
        if (first == 127 || first == 0) continue;
        if (!judge_ip(v[1]) || !is_mask(v[1])) err++;
        else {
            if (!judge_ip(v[0])) err++;
            else {
                int first = stoi(v[0].substr(0, v[0].find_first_of('.')));
                if (is_private(v[0])) p++;
                if (first > 0 && first < 127) a++;
                else if (first > 127 && first < 192) b++;
                else if (first > 191 && first < 224) c++;
                else if (first > 223 && first < 240) d++;
                else if (first > 239 && first < 256) e++;
            }
        }
    }
    cout << a << " " << b << " " << c << " " << d << " " << e << " " << err << " "
         << p << endl;
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值