IP黑名单匹配(华为2021实习笔试)

本文介绍了一种C++方法,用于判断给定的IP地址是否属于黑名单,通过CIDR(Classless Inter-Domain Routing)掩码表示的多个IP和网段。核心是利用掩码进行精确的二进制比较,适用于大规模IP检查和性能优化。
摘要由CSDN通过智能技术生成

题目:找出n个IP中的黑名单IP

黑名单定义:给定了m个IP,mask采用CIDR表示,网段相同则判定为黑名单

example:

illegal_ip_01:  192.168.254.121/24

illegal_ip_02:   116.7.221.23/16

 test_ip_01:   192.168.254.11

 test_ip_02:   116.7.222.1

上述给定的两个test IP均不合法。

下面提供了c++解法

注:批量IP检查可以直接调用下面接口暴力循环,也可以先将所有的不合法IP转换为二进制保存到数组,然后再依次遍历,可以节约不少时间。

bool judgeLegelIp(string mask,string test){
    //将字符串转换为两个32位无符号整型进行比较
    uint32_t mask_bit=0;
    int i=0, k=3;
    while(i< mask.size()){
        string tempStr;    
        while(mask[i]!='.'&&mask[i]!='/'){
            tempStr+=mask[i++];
        }
        uint32_t b(stoi(tempStr)<<(k--)*8);
        mask_bit |= b;
        if(mask[i]=='/')
            break;
        ++i;
    }
    ++i;
    string temps;
    while(i<mask.size()){
        temps+=mask[i++];
    }
    uint32_t mask_bitcnt(stoi(temps));//记录掩码位数
    uint32_t test_bit=0;
    int j=0,m=3;
    while(j<test.size()){
        string s1;
        while(j<test.size()&&test[j]!='.'){
            s1+=test[j++];
        }
        uint32_t b(stoi(s1)<<(m--)*8);
        test_bit |= b;
        ++j;
    }
    mask_bit>>=(32-mask_bitcnt);
    test_bit>>=(32-mask_bitcnt);
    return (mask_bit^test_bit);  
}
//test example
int main(){
    string s1("192.168.254.11/24");
    string s2("192.168.254.221");
    string s3("192.168.221.1");
    if(judgeLegelIp(s1,s2))
        cout<<"legel IP"<<endl;
    else 
        cout<<"illegel IP";
    return 0;
}

完整优化版本:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>    //stringstream
using namespace std;

//c++实现split函数功能
vector<string> split(string s, char c){
    stringstream ss(s);
    vector<string> ans;
    string tmpStr;
    while(getline(ss,tmpStr,c)){
        if(!tmpStr.empty()){
            ans.push_back(tmpStr);
        }
    }
    return ans;
}

uint32_t testip_to_num(string s){
    vector<string> res2 = split(s,'.');
    uint32_t ip_num = 0;
    int k =3;
    for(int i = 0; i < 4; ++i){
        ip_num |= (stoi(res2[i]) << 8*(k--));
    }
    return ip_num;
} 

pair<uint32_t, int> maskip_to_num(string s){
    pair<uint32_t, int>ans;
    vector<string> res1 = split(s,'/');
    string s1 = res1.front();
    vector<string> res2 = split(s1,'.');
    uint32_t ip_num = 0;
    int k =3;
    for(int i = 0; i < 4; ++i){
        ip_num |= (stoi(res2[i]) << 8*(k--));
    }
    int bit_str = stoi(res1.back());
    ans = make_pair(ip_num, bit_str);
    return ans;
}

bool is_black_ip(string maskip, string test_ip){
    pair<uint32_t, int> pp = maskip_to_num(maskip);
    uint32_t testip = testip_to_num(test_ip);
    if((testip >> (32 - pp.second)) == (pp.first >> (32 - pp.second))){
        return true;
    }
    return false;
}

int main (){
    int m,n;
    cin>>m>>n;
    string mask;
    string test;
    vector<string>v1(m),v2(n);
    int i = 0, j = 0;
    while(cin>>v1[i++], i < m);
    while(cin>>v2[j++], j < n);
    //output black ip
    for(auto s2 : v2){
        for(auto s1 : v1){
            if(is_black_ip(s1,s2)){
                cout<<s2<<endl;
            }
        }
    }
    return 0;
}

/*
//test example
2 4
121.121.121.28/24
113.121.121.23/20
121.121.121.121
113.121.116.198
113.121.144.2
224.121.121.112
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值