【子网划分工具的设计与实现 】

题目3  子网划分工具的设计与实现  (以软件形式验收,要求能够讲授相应的子网划分的原理及过程,基本要求是定长子网划分,若能考虑实现可变长子网划分,作为成绩提升的一个考量)   
1、设计要求 
(1)编程实现一个子网划分的简单工具。 
(2)能够根据用户输入的网络地址和子网掩码,判断出用户输入的合法性及网络的类别(A、B、C地址)。 
(3)能够计算出下列参数:子网数及有效子网、每个子网的主机数、每个子网IP范围及广播地址。 
(4)应有相应的帮助提示及良好的结果输出组织,易于用户使用和查看结果。

子网划分原理

有很多博客已经讲的非常好了,请各位自行百度(❁´◡`❁)

代码实现

下面给出C++实现供需要的小伙伴参考。写的时候时间紧,代码有些凌乱,大家多多包涵,欢迎大佬指正

#include <iostream>
#include <string>
#include <sstream>
#include <math.h>
#include <string.h>
#include <bitset>
#include <vector>
#include <algorithm>
#include <utility>

using namespace std;

class dotDec{   
public:
    dotDec(){}
    ~dotDec(){}
    /**
     * 用点分10进制数组来更新它对应的二进制数
    */
    void update_dtob(){
        bin=0;
        for (int i=0;i<4;++i){
            bin |= (dec[i] & _mask);
            if (i==3) break;
            bin <<= 8;
        }
    }
    /**
     * 用二进制数更新它对应的点分10进制数组
    */
    void update_btod(){
        memset(dec,0,sizeof(dec));
        unsigned int tmp = bin;
        for (int i=3;i>=0;--i){
            dec[i] |= (tmp & _mask);
            tmp >>= 8;
        }
    }
    /**
     * 返回一个点分10进制的字符串
     * 注意:调用前及时更新10进制数组
    */
    string toString(){
        stringstream ss;
        ss<<dec[0]<<"."<<dec[1]<<"."<<dec[2]<<"."<<dec[3];
        return ss.str();
    }
    int _mask = (1<<8) -1;
    int dec[4];
    unsigned int bin;
};

class subnetPartitioning{
public:
    subnetPartitioning(){}
    ~subnetPartitioning(){}
    /**
     * 检查输入数据的格式,并将输入的点分10进制字符串转换成整数数组
    */
    void extractVals(const string &str,dotDec* data){
        int startPos=0, j=0;
        for (int i=0;i<str.size(),j<4;++i){
            if ((str[i]<'0' || str[i]>'9') && str[i]!='.') throw "输入格式错误";
            if (str[i]=='.' || i==str.size()-1){
                data->dec[j] = stoi(str.substr(startPos,i-startPos+1));
                if (data->dec[j] > 255) throw "输入格式错误";
                startPos = i+1;
                ++j;
            }
        }
        if (j!=4) throw "输入格式错误";
        data->update_dtob();
    }
    /**
     * 求一个整数的二进制的前bit位中有多少个1
     * @param n 整数
     * @param bit 前bit位
    */
    int numof_1(unsigned int n, int bit){
        int num=0;
        for (int i=0;i<bit;++i){
            if (n>>i & 1) ++num;
        }
        return num;
    }
    /**
     * 检查掩码是否合法
    */
    void checkMask(){
        if ((mask.dec[3]!=0 && (mask.dec[2]!=255 && mask.dec[1]!=255 && mask.dec[0]!=255)) ||
            (mask.dec[2]!=0 && mask.dec[2]!=255 && (mask.dec[1]!=255 && mask.dec[0]!=255 && mask.dec[3]!=0)) ||
            (mask.dec[1]!=0 && mask.dec[1]!=255 && (mask.dec[0]!=255 && mask.dec[1]!=0 && mask.dec[2]!=0))
         ) throw "掩码格式错误";
    }
    /**
     * 检查ip类型
    */
    void checkIP(){
        if (ip.dec[0] > 0 && ip.dec[0] <= 126) {
            netType='A';
            cout<<"本IP类型为A类"<<endl;
        } else if (ip.dec[0] >= 128 && ip.dec[0] <= 191) {
            netType='B';
            cout<<"本IP类型为B类"<<endl;
        } else if (ip.dec[0] >= 192 && ip.dec[0] <= 223) {
            netType='C';
            cout<<"本IP类型为C类"<<endl;
        } else {
            throw "无效的IP地址类别";
        }
    }
    /**
     * 静态子网划分,因为题目没有提到在这一步需要输入要划分的子网数
     * 所以这个实际上是通过主机ip和子网掩码来推断原始的网络地址和可以划分的子网数
    */
    void subnets(){
        int borrowedHosts = 0;  //借用的主机位
        int networkBit = numof_1(mask.bin,32);   //网络位
        int nowPos = -1;    //当前借位的位置(32位分成4段,这个表示发生借位的那一段)
        networkAddress.bin = (ip.bin & mask.bin);   //计算网络地址
        networkAddress.update_btod();
        for (int i=0;i<4;++i){
           if (mask.dec[i]==255) continue;
           nowPos = i;
           break;
        }
        if (netType=='A'){
            borrowedHosts = networkBit - 8;
        } else if (netType=='B') {
            borrowedHosts = networkBit - 16;
        }else if (netType=='C'){
            borrowedHosts = networkBit - 24;
        } 
        int hostBit = 32 - networkBit;   //主机位
        int numOfsubnets = pow(2,borrowedHosts);    //子网数
        int numOfAvailableHosts = pow(2,hostBit) - 2;    //每子网可用主机数
        
        cout<<"子网数:"<<numOfsubnets<<endl;
        cout<<"每子网可用主机数:"<<numOfAvailableHosts<<endl;

        int stepSize = 256 - mask.dec[nowPos];   //子网增量
        cout<<"有效子网:"<<stepSize-2<<endl<<endl;

        // 淦! (╯°□°)╯︵ ┻━┻
        // 或许应该把IP及其二进制数作为一个整体封装一下

        dotDec start=networkAddress, end=networkAddress;
        end.bin |= (((1<<borrowedHosts) -1)<<hostBit);
        while(start.bin<=end.bin){
            dotDec s_ip = start ,e_ip = start;
            s_ip.bin &= ~((1<<hostBit)-1);  //主机位全设为0
            e_ip.bin |= ((1<<hostBit)-1);   //主机位全设为1
            s_ip.update_btod();
            e_ip.update_btod();
            cout<<"网络号:"<<s_ip.toString()<<endl;
            cout<<"广播地址:"<<e_ip.toString()<<endl;
            cout<<"IP范围:"<<s_ip.toString()<<"~"<<e_ip.toString()<<endl;
            //下面计算可用ip
            s_ip.bin += 1;
            e_ip.bin -= 1;
            s_ip.update_btod();
            e_ip.update_btod();
            cout<<"可用IP范围:"<<s_ip.toString()<<"~"<<e_ip.toString()<<endl<<endl;
            start.bin += (1<<hostBit);
        } 
    }
    /**
     * 寻找最少需要几位主机位才能表示当前的主机数
     * @param host 主机数
     * @return 需要的主机位数
    */
    int findMinLenHostBit(int host){
        for (int i=0;i<32;++i){
            if ((1<<i)-2 >= host) return i;
        }
        throw "主机位不够!";
        return -1;
    }
    /**
     * 动态子网划分
     * @param hostNum 包含若干pair<int,int>的vector,pair.first为序号,pair.second为主机数
    */
    void vlsm_subnets(vector<pair<int,int>> hostNum){
        sort(hostNum.begin(),hostNum.end(),[](pair<int,int>& a, pair<int,int>& b)->bool {return a.second>b.second;});
        // 先排序,从最大主机数开始划分
        int networkBit = numof_1(mask.bin,32);      //网络位
        networkAddress.bin = ip.bin & mask.bin;     //网络地址
        networkAddress.update_btod();
        for (int i=0;i<hostNum.size();++i){
            int hostBit = findMinLenHostBit(hostNum[i].second);
            int borrowedHostBit = 32 - hostBit - networkBit;    //可借用的主机位,用来表示子网
            if (borrowedHostBit<=0) throw "可借用的主机位不足";
            dotDec s_ip = networkAddress ,e_ip = networkAddress, newMask;
            s_ip.bin &= ~((1<<hostBit)-1);
            e_ip.bin |= ((1<<hostBit)-1);
            s_ip.update_btod();
            e_ip.update_btod();
            cout<<"第"<<hostNum[i].first<<"个子网:"<<endl;
            cout<<"网络号:"<<s_ip.toString()<<endl;
            cout<<"广播地址:"<<e_ip.toString()<<endl;
            cout<<"IP范围:"<<s_ip.toString()<<"~"<<e_ip.toString()<<endl;
            //下面计算可用ip
            s_ip.bin += 1;
            e_ip.bin -= 1;
            s_ip.update_btod();
            e_ip.update_btod();
            cout<<"可用IP范围:"<<s_ip.toString()<<"~"<<e_ip.toString()<<endl;
            newMask.bin = ~0;
            newMask.bin &= ~((1<<hostBit)-1);
            newMask.update_btod();
            cout<<"子网掩码:"<<newMask.toString()<<endl<<endl;
            networkAddress.bin += (1<<hostBit);
        }
    }

    bool input(){
        string str;
        try{
            cout<<"请输入网络地址(格式如:x1.x2.x3.x4):"<<endl;
            cin>>str;
            extractVals(str,&ip);
            cout<<"请输入子网掩码(格式为:m1.m2.m3.m4):"<<endl;
            cin>>str;
            extractVals(str,&mask);
            checkMask();
            checkIP();
        }catch(const char* e){
            cout<<e<<endl;
            return false;
        }
        return true;
    }
    bool input2(){
        string str;
        int subnet,x;
        vector<pair<int,int>> hostNum;
        try{
            cout<<"请输入网络地址(格式如:x1.x2.x3.x4):"<<endl;
            cin>>str;
            extractVals(str,&ip);
            cout<<"请输入子网掩码(格式为:m1.m2.m3.m4):"<<endl;
            cin>>str;
            extractVals(str,&mask);
            checkMask();
            checkIP();
            cout<<"请输入要划分的子网数:";
            cin>>subnet;
            if (subnet<=0) throw "输入有误";
            for (int i=0 ;i<subnet;++i){
                cout<<"输入第"<<i+1<<"个子网的主机数:";
                cin>>x;
                hostNum.push_back(make_pair(i,x));
            }
            vlsm_subnets(hostNum);
        }catch(const char* e){
            cout<<e<<endl;
            return false;
        }
        return true;
    }
private:
    dotDec ip;
    dotDec mask;
    dotDec networkAddress;
    char netType;
};

int main(){
    subnetPartitioning test;
    cout<<"请选择功能,1.静态子网划分,2.可变长子网划分,3.退出"<<endl;
    int x;
    while(cin>>x){
        if(x==1){
            while (!test.input());
            test.subnets();
        }else if(x==2){
            while (!test.input2());
        }else{
            break;
        }
        cout<<"请选择功能,1.静态子网划分,2.可变长子网划分,3.退出"<<endl;
    }
    return 0;
}```

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值