【问题标题】:boost asio - check if ip is from a particular subnetboost asio - 检查 ip 是否来自特定子网
【发布时间】:2021-01-28 13:21:45
【问题描述】:

我必须检查 IP 地址是否属于预定义的子网。例如,IP 地址 192.168.0.1 在 CIDR 范围 192.168.0.0/24 中。

我试过了:

有一种方法:

is_subnet_of 用于 network_v4 类,但与 adress_v4 没有类似之处。我错过了什么吗?

【问题讨论】:

  • ip::address_v4 中有关子网的大多数方法都已弃用,因此您可能必须使用 ip::network_v4
  • @ThomasSablik 那么如何使用 network_v4 处理此任务?
  • 您可以创建ip::network_v4ip::network_v4::network_v4 并比较network
  • @ThomasSablik 是这样的:network_v4 addr = make_network_v4("192.168.0.1/32"); network_v4 net = make_network_v4("192.168.0.0/24"); cout << addr.is_subnet_of(net) << endl; 所以基本上 - 威胁一个 IP 地址作为掩码为 32 的子网?它看起来不像是一个优雅的解决方案。
  • 不,我的意思是network_v4 addr = make_network_v4("192.168.0.1/24"); addr.network == address_v4("192.168.0.0/24");

标签: c++ boost-asio


【解决方案1】:
    using namespace boost::asio;
    // make a subnet with 255.255.255.0
    ip::network_v4 subnet = ip::make_network_v4("192.168.0.0/24");
    // get all the hosts from this subnet
    ip::address_v4_range hosts = subnet.hosts();

    boost::system::error_code error_code;
    // create target address
    ip::address addr = ip::make_address("192.168.0.1", error_code);
    if (error_code)
    {
        throw std::invalid_argument(error_code.message());
    }

    // Now check if the address is one of the hosts in the subnet
    if(hosts.find(addr.to_v4()) != hosts.end()) {
        std::cout << "yes" << std::endl;
    }

【讨论】:

  • 您应该解释为什么这是原始问题的解决方案。好像不是这样……
  • 如果我理解正确,OP 想检查 192.168.0.1 是否属于 192.168.0.0/24?你得到了答案,它是
  • 再次,您需要解释您在回答中做了什么!
  • 好的,我明白了……这是一小段代码,我认为任何对C++有一点了解的人都应该理解它没有问题。但是不,我错了:)。我应该发表一些评论
【解决方案2】:

您需要创建一个由 IP 和前缀长度(= 子网)组成的网络对象。请注意,IP 可能是,但不一定是网络 IP。网络 IP 在 Asio 的网络类中被称为规范。 (网络 IP 是您子网中的第一个 IP。例如,192.168.13.15/24 具有规范 IP 192.168.13.0。)

然后,您从您的测试 IP 创建第二个网络,其前缀长度与您的参考网络相同,并比较网络的规范 IP。 (您可以直接比较规范网络,但这包括我们知道它们相等的前缀长度。代码少一点,但效率也低一点。)

#include <asio.hpp>

#include <iostream>
#include <iomanip>

namespace ip = asio::ip;

bool contains(ip::network_v4 const& network, ip::address_v4 const& ip){
    return network.canonical().address() ==
        ip::network_v4(ip, network.prefix_length()).canonical().address();
}

int main(){
    auto const make = [](auto const v){ return ip::make_address_v4(v); };
    std::cout << std::boolalpha
        << contains({make("192.168.0.5"), 24}, {make("192.168.0.200")}) << "\n"
        << contains({make("192.168.0.5"), 24}, {make("192.168.0.6")}) << "\n"
        << contains({make("192.192.0.5"), 24}, {make("192.168.0.200")}) << "\n"
        << contains({make("192.192.0.5"), 24}, {make("192.168.0.6")}) << "\n"
        << contains({make("192.168.0.5"), 30}, {make("192.168.0.200")}) << "\n"
        << contains({make("192.168.0.5"), 30}, {make("192.168.0.6")}) << "\n";
}

注意 1: 您可以将 make 替换为 ip::make_address_v4。它只是在这里进行良好的代码格式对齐的捷径。

注意 2: 如果您使用 Boost.Asio 而不是独立的 Asio,只需将 &lt;asio.hpp&gt; 替换为 &lt;boost/asio.hpp&gt; 并将 ip = asio::ip 替换为 ip = boost::asio::ip

输出:

true
true
false
false
false
true

我打开了一个向网络类添加contains 方法的问题:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-02
    • 2010-10-09
    • 2012-04-17
    • 1970-01-01
    • 2012-08-07
    • 1970-01-01
    • 2021-06-20
    • 2014-02-20
    相关资源
    最近更新 更多