【问题标题】:Print all IPs based on IP and mask C++根据 IP 打印所有 IP 并掩码 C++
【发布时间】:2017-11-01 21:37:23
【问题描述】:

我想打印给定掩码的所有可能 IP。我有这个代码来获取它,但我似乎遗漏了一些东西,因为我无法获得 IP 列表。我的代码基于this other post

unsigned int ipaddress, subnetmask;     

inet_pton(AF_INET, b->IpAddressList.IpAddress.String, &ipaddress);
inet_pton(AF_INET, b->IpAddressList.IpMask.String, &subnetmask);

for (unsigned int i = 1; i<(~subnetmask); i++) {
    auto ip = ipaddress & (subnetmask + i);
}

示例:ipaddress= 172.22.0.65 netmask= 255.255.252.0

我希望:

172.22.0.1 172.22.0.2 172.22.0.3 172.22.0.4 ...

更新:我试过这段代码,但它也不起作用:

char* ip = "172.22.0.65";
char* netmask = "255.255.252.0";

struct in_addr ipaddress, subnetmask;

inet_pton(AF_INET, ip, &ipaddress);
inet_pton(AF_INET, netmask, &subnetmask);

unsigned long first_ip = ntohl(ipaddress.s_addr & subnetmask.s_addr);
unsigned long last_ip = ntohl(ipaddress.s_addr | ~(subnetmask.s_addr));

for (unsigned long ip = first_ip; ip <= last_ip; ++ip) {
    unsigned long theip = htonl(ip);
    struct in_addr x = { theip };
    printf("%s\n", inet_ntoa(x));
}

【问题讨论】:

  • 如果您知道您的代码是在 C++ 中,那么为什么还要添加 C
  • 编辑为包含 C 和 C++
  • 回滚是因为 C 和 C++ 的答案会有很大不同。两者都想要,问两个问题。
  • 考虑网络掩码:例如 1.200.17.64。上面的 for 循环不起作用。
  • @RichardCritten 这不是网络掩码。

标签: c++ network-programming ip netmask


【解决方案1】:

您正在 anding 带有子网掩码的 IP 地址添加(本质上是 ored)与不断变化的主机部分。这里的优先级是错误的。您应该使用网络掩码获取 IP 地址以获取 network 部分,然后 获取那里的主机部分:

auto ip = (ipaddress & subnetmask) | i;

另外,inet_pton 的结果不是int,而是struct in_addr,所以无论如何都是YMMV。最有可能的是,您应该使用inet_addr,因为它返回uint32_t

ip_address = inet_addr("127.0.0.1");

但是你的代码又一次期望127 是最重要的字节,它不在 LSB 系统上。因此,您需要将这些地址与ntohl 交换一次,然后与htonl 交换。

因此我们得到如下结果:

uint32_t ipaddress;
uint32_t subnetmask;

ipaddress = ntohl(inet_addr(b->IpAddressList.IpAddress.String));
subnetmask = ntohl(inet_addr(b->IpAddressList.IpMask.String));

for (uint32_t i = 1; i<(~subnetmask); i++) {
    uint32_t ip = (ipaddress & subnetmask) | i;
    struct in_addr x = { htonl(ip) };
    printf("%s\n", inet_ntoa(x));
}

【讨论】:

  • 使用您的代码,IP 172.0.0.0 一直被打印出来。 ipaddress 为 0xac160040,subnermask 为 0xfffffc00。我在帖子中使用的示例的正确结果是pastebin.com/x4MYei7H
【解决方案2】:

您可以按位AND 输入IP 地址和输入掩码来确定范围内的第一个IP,并按位OR 输入IP 地址和掩码的倒数来确定范围内的最后一个IP。然后你可以循环遍历它们之间的值。

另外,inet_pton(AF_INET) 需要一个指向 struct in_addr 的指针,而不是 unsigned int

试试这个:

struct in_addr ipaddress, subnetmask;

inet_pton(AF_INET, b->IpAddressList.IpAddress.String, &ipaddress);
inet_pton(AF_INET, b->IpAddressList.IpMask.String, &subnetmask);

unsigned long first_ip = ntohl(ipaddress.s_addr & subnetmask.s_addr);
unsigned long last_ip = ntohl(ipaddress.s_addr | ~(subnetmask.s_addr));

for (unsigned long ip = first_ip; ip <= last_ip; ++ip) {
    unsigned long theip = htonl(ip);
    // use theip as needed...
}

例如:

172.22.0.65 & 255.255.252.0 = 172.22.0.0
172.22.0.65 | 0.0.3.255 = 172.22.3.255

【讨论】:

  • 嗨,它在以下行抱怨“错误 C2678:二进制 '&':未找到采用 'ULONG' 类型的左操作数(或没有可接受的转换)的运算符”计算first_iplast_ip。尝试将 subnetmask 更改为 subnetmask.s_addr 但循环未提供预期的 IP
  • 我忘记将s_addr 应用到subnetmaskntohl()htonl() 到生成的IP。我已经修好了。
  • 我更新了问题中的代码,因为您的代码现在似乎也不起作用。我设置了 ip 和网络掩码,所以你可以测试它是否工作正常。谢谢!
  • 我在发布之前测试了更新的代码。事实上,我已经在循环中使用inet_ntoa() 对其进行了测试,就像您所做的那样。正如我展示的那样,它对我来说很好,并打印了正确的 IP。但是,您在循环中调用了两次htonl(),因此您实际上是在取消它并使用错误的字节顺序打印 IP。将struct in_addr x = { htonl(theip) }; 更改为struct in_addr x = { theip };,因为theip 已经是inet_ntoa() 所期望的字节顺序。
  • 这不是我运行我展示的代码时得到的。正如预期的那样,我得到了172.22.0.1 172.22.0.2 172.22.0.3 172.22.0.4 ...。在 Windows 上,in_addrunion,因此使用 = { theip } 语法初始化 struct in_addr x 不会初始化正确的字段。请改用struct in_addr x; x.s_addr = theip;
猜你喜欢
  • 2019-08-21
  • 2011-01-14
  • 2011-07-28
  • 2016-11-30
  • 2020-12-22
  • 2010-10-21
  • 2013-12-08
  • 2014-12-31
  • 2012-05-17
相关资源
最近更新 更多