【问题标题】:Conversion of IP address to integer [duplicate]IP地址到整数的转换[重复]
【发布时间】:2012-04-23 15:38:20
【问题描述】:

可能重复:
IP Address to Integer - C

如何将 IP 地址转换为具有以下形式的整数: A.B.. 或 A.B.C.* 或 A...* 或 ... 我想编写一个 C 程序,它可以确定一个 IP 地址是否是另一个 IP 地址的子集。例如,IP 地址 192.168.125.5 是 192.168.. 的子集。现在我想将两个 IP 地址都转换为唯一的整数,然后检查一个是否是另一个的子集。有没有办法做到这一点?

【问题讨论】:

  • 您根本不想将 IP 地址转换为整数。首先,仅适用于 IPv4。您想将它们转换为适当长度的字节数组,然后对它们进行网络掩码操作。
  • 如果你的平台有inet_pton()

标签: c networking


【解决方案1】:

您想要确定一个 IP 地址是否在子网中,并为此应用网络掩码。可能已经有(当然)图书馆可以做你想做的事。如果你想自己动手,那就这样吧。

如果此 IP 地址来自受信任的来源(即,不是用户),那么您可以简单地通过执行以下操作从标准 C 字符串中提取 IP 地址:

char ipAddressString[16] = "192.168.125.5"
char netMaskString[16] = "255.255.0.0"
char subnetString[16] = "192.168.0.0"

uint32_t ipAddress = parseIPV4string(ipAddressString);
uint32_t netmask = parseIPV4string(netmaskString);
uint32_t subnet = parseIPV4string(subnetString);

if (ipAddress & netmask == subnet) {
  return true;
}

uint32_t parseIPV4string(char* ipAddress) {
  char ipbytes[4];
  sscanf(ipAddress, "%uhh.%uhh.%uhh.%uhh", &ipbytes[3], &ipbytes[2], &ipbytes[1], &ipbytes[0]);
  return ipbytes[0] | ipbytes[1] << 8 | ipbytes[2] << 16 | ipbytes[3] << 24;
}

【讨论】:

  • 很好,也感谢解析器逻辑!
  • 将 int (%d) 读入 char (ipbytes[x]) 指针会导致严重错误,因为 sscanf 会将 sizeof(int) 字节写入 ipbytes[x] 指向的内存。这个例子很危险。
  • @Zac 好尴尬!我已经修复了错误。
【解决方案2】:

IP 地址,例如192.168.0.1 可以很容易地写成一个整数,只需用十六进制写成 0xC0 0xA8 0x00 0x01 或只是 0xC0A80001

那么这只是一个位匹配的情况,所以你构造一个对应的子网掩码,255.255.0.0,它就是 0xFFFF0000,你可以通过这样做来测试两者是否匹配:

0xC0A80001 & 0xFFFF0000 == 0xC0A80000 & 0xFFFF0000

其中平等测试的一侧是“您关心的基本内容”,另一侧是真实地址,给定的掩码在两侧都是相同的。

一般而言,您可以通过将“*”设置为 0 并将实际数字设置为 0xFF 来构建合适的掩码,如果您想要更细粒度的掩码,则很难用“*”表示。

【讨论】:

    【解决方案3】:

    简单且非通用的方法是使用 sscanf (with int a, b, c, d): sscanf(ip, "%d.%d.%d.%d", &amp;a, &amp;b, &amp;c, &amp;d); 但它只有在您拥有所有部分的 ip 时才有效:10.47.100.1

    如果不是这样,你仍然可以使用sscanf的返回值,它会告诉你它成功找到了多少匹配(或EOF)。

    获得这 4 个数字后,您可以检查子集关系。

    【讨论】:

    • 不,我想将IP地址转换为整数,然后检查子集关系....
    • 你仍然可以从你得到的 4 中构造一个整数。困难的部分是解析整数。稍后,您可以按照其他人在此处的建议将它们向左移动。
    【解决方案4】:

    单个整数(假设为 32 位)不足以表示您所概述的内容。您需要更多信息才能表示星号。

    例如,您可以有一对(地址,网络掩码),其中网络掩码是一个表示有效高位位数的单个小整数,例如网络地址,例如“10.0.0.0 " 可以由对 (0x0a000000, 8) 表示。如果出于某种原因您真的希望能够在地址中的“任何地方”使用通配符,则每个地址位都需要一个完整的标志位,因此需要两个 32 位整数。然后您可以将“192.168..”之类的东西表示为对 (0xc0a80000, 0xffff0000)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-18
      • 2010-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 2014-03-03
      • 2010-12-13
      相关资源
      最近更新 更多