判断一个IP区间(或IP)是否被另一个IP区间所包含

本文介绍了一种处理IP地址的方法,包括验证IP地址的有效性、将IP地址转换为数值形式、格式化IP地址以及比较两个IP地址的大小。此外,还提供了判断一个IP地址是否位于指定的IP区间内的方法,并能判断两个IP区间是否重叠,如果重叠,则返回合并后的IP区间。
部署运行你感兴趣的模型镜像

以下方法实现判断一个IP是否被一个IP区间所包含

有一些静态方法可能引用了同名空间的自定义的类,

至于合并两个相临的IP段,可对其中的最大或最小IP+1

using System;
using System.Text.RegularExpressions;

namespace HKH.Common
{
 /// <summary>
 /// clsMacAndIP 的摘要说明。
 /// </summary>
 public class clsIPAddress
 {
  private clsIPAddress()
  {
  }


  #region 判断是否合法 IP

  /// <summary>
  /// 判断是否合法 IP
  /// </summary>
  /// <param name="strIP"></param>
  /// <returns></returns>
  public static bool ValidateIPAddress(string strIP)
  {
   if ( null == strIP || "" == strIP.Trim() || Convert.IsDBNull(strIP) )
    return false;

   return Regex.IsMatch(strIP,@"^((/d{1,2}|1/d/d|2[0-4]/d|25[0-5])/.){3}(/d{1,2}|1/d/d|2[0-4]/d|25[0-5])$");
  }

  #endregion

  #region 转换成数值

  /// <summary>
  ///  转换为数值
  /// </summary>
  /// <param name="IPAddr"></param>
  /// <returns></returns>
  public static uint TransNum(string IPAddr)
  {
   if ( !ValidateIPAddress(IPAddr) )
    throw new Exception("IP Address isn't Well Format!");

   string[] IPStrArray = new string[4];
   IPStrArray = IPAddr.Split('.');
   return MAKELONG(MAKEWORD(byte.Parse(IPStrArray[3]),byte.Parse(IPStrArray[2])),MAKEWORD(byte.Parse(IPStrArray[1]),byte.Parse(IPStrArray[0])));
  }

  #endregion

  #region 格式化

  /// <summary>
  /// 格式化
  /// </summary>
  /// <param name="IPAddr"></param>
  /// <returns></returns>
  public static string Format(string IPAddr)
  {
   if (IPAddr[0] == '.')
    IPAddr = "0" + IPAddr;

   if (IPAddr[IPAddr.Length - 1] == '.')
    IPAddr += "0.0.0.";
   else
    IPAddr += ".0.0.0.";

   IPAddr = IPAddr.Substring(0,clsString.IndexOf(IPAddr,".",4));

//   //去掉无用的0
//   IPAddr = Regex.Replace(IPAddr,"^0{1,2}","");
//   IPAddr = Regex.Replace(IPAddr,@"/.+0{1,2}",".");

   if ( ValidateIPAddress(IPAddr) )
    return IPAddr;

   return "0.0.0.0";
  }

  #endregion

  #region 比较两个IP的大小

  /// <summary>
  /// 比较两个IP的大小
  /// </summary>
  /// <param name="IP1"></param>
  /// <param name="IP2"></param>
  /// <returns></returns>
  public static int Compare(string IP1,string IP2)
  {
   if ( !(ValidateIPAddress(IP1) && ValidateIPAddress(IP2)))
    throw new Exception("IP Address isn't Well Format!");

   uint IPNum1 = TransNum(IP1);
   uint IPNum2 = TransNum(IP2);

   if (IPNum1 == IPNum2 )
    return 0;

   return IPNum1 > IPNum2 ? 1 : -1 ;
  }


  #endregion

  #region 判断一个IP是否包含在指定IP区间内

  /// <summary>
  /// 判断一个IP是否包含在指定IP区间内
  /// </summary>
  /// <param name="IPRegion"></param>
  /// <param name="IP"></param>
  /// <returns></returns>
  public static bool IsInclude(string[] IPRegion,string IP)
  {
   //验证
   if ( null == IPRegion || null == IP || 0 == IPRegion.Length )
    return false;

   if ( !ValidateIPAddress(IP) )
    return false;

   if ( 1 == IPRegion.Length )
   {
    if ( !ValidateIPAddress(IPRegion[0]) )
     return false;
    
    if ( 0 == Compare(IPRegion[0],IP) )
     return true;
   }

   if ( !(ValidateIPAddress(IPRegion[0]) && ValidateIPAddress(IPRegion[1])) )
    return false;

   uint IPNum = TransNum(IP);
   uint IPNum1 = TransNum(IPRegion[0]);
   uint IPNum2 = TransNum(IPRegion[1]);

   //比较
   if ( Math.Min(IPNum1,IPNum2) <= IPNum && Math.Max(IPNum1,IPNum2) >= IPNum )
    return true;
   
   return false;
  }


  #endregion

  #region 判断两个IP区间是否重叠,重叠则返回合并区间,否则返回 NULL

  /// <summary>
  /// 判断两个IP区间是否重叠,重叠则返回合并区间,否则返回 NULL
  /// </summary>
  /// <param name="IPRegion1"></param>
  /// <param name="IPRegion2"></param>
  /// <returns></returns>
  public static string[] CheckOverlapAndMerge(string[] IPRegion1,string[] IPRegion2)
  {
   //验证
   if ( null == IPRegion1 || null == IPRegion2 || 0 == IPRegion1.Length || 0 == IPRegion2.Length )
    return null;

   //分数组长度进行处理 =1 和 > 1
   if ( 1 == IPRegion1.Length )
   {
    if (!ValidateIPAddress(IPRegion1[0]))
     throw new Exception("IP Address isn't Well Format!");

    if ( 1 == IPRegion2.Length )
    {
     if (!ValidateIPAddress(IPRegion2[0]))
      throw new Exception("IP Address isn't Well Format!");
     
     //相等
     if ( Equals(IPRegion1[0],IPRegion2[0]) )
      return IPRegion1;
    }
    // > 1
    else
    {
     if ( !(ValidateIPAddress(IPRegion2[0]) && ValidateIPAddress(IPRegion2[1])) )
      throw new Exception("IP Address isn't Well Format!");
     
     if ( IsInclude(IPRegion2,IPRegion1[0]) )
      return IPRegion2;
    }
   }
   // >1
   else
   {
    if ( !(ValidateIPAddress(IPRegion1[0]) && ValidateIPAddress(IPRegion1[1])) )
     throw new Exception("IP Address isn't Well Format!");

    if ( 1 == IPRegion2.Length )
    {
     if (!ValidateIPAddress(IPRegion2[0]))
      throw new Exception("IP Address isn't Well Format!");
     
     if ( IsInclude(IPRegion1,IPRegion2[0]) )
      return IPRegion1;
    }
    // > 1
    else
    {
     if ( !(ValidateIPAddress(IPRegion2[0]) && ValidateIPAddress(IPRegion2[1])) )
      throw new Exception("IP Address isn't Well Format!");
     
     uint IPNum1_1 = TransNum(IPRegion1[0]);
     uint IPNum1_2 = TransNum(IPRegion1[1]);
     uint IPNum2_1 = TransNum(IPRegion2[0]);
     uint IPNum2_2 = TransNum(IPRegion2[1]);
     
     #region 大小格式整理 IP[0] <= IP[1]

     if ( IPNum1_1 > IPNum1_2 )
     {
      string stemp = IPRegion1[0];
      IPRegion1[0] = IPRegion1[1];
      IPRegion1[1] = stemp;

      uint utemp = IPNum1_1;
      IPNum1_1 = IPNum1_2;
      IPNum1_2 = utemp;
     }

     if ( IPNum2_1 > IPNum2_2 )
     {
      string stemp = IPRegion2[0];
      IPRegion2[0] = IPRegion2[1];
      IPRegion2[1] = stemp;

      uint utemp = IPNum2_1;
      IPNum2_1 = IPNum2_2;
      IPNum2_2 = utemp;
     }

     #endregion

     #region 判断合并

     //互不包含
     if ( IPNum1_1 > IPNum2_2 || IPNum1_2 < IPNum2_1 )
      return null;

     //合并
     string[] result = new string[2];

     result[0] = IPNum1_1 < IPNum2_1 ? IPRegion1[0] : IPRegion2[0] ;
     result[1] = IPNum1_2 > IPNum2_2 ? IPRegion1[1] : IPRegion2[1] ;

     return result;

     #endregion
    }

   }

   return null;
  }


  #endregion

  #region 私有方法

  /// <summary>
  /// 移位转换_8
  /// </summary>
  /// <param name="bLow"></param>
  /// <param name="bHigh"></param>
  /// <returns></returns>
  private static ushort MAKEWORD(byte bLow,byte bHigh)
  {
   return ((ushort) (((byte) (bLow)) | ((ushort) ((byte) (bHigh))) << 8));
  }

  /// <summary>
  /// 移位转换_16
  /// </summary>
  /// <param name="bLow"></param>
  /// <param name="bHigh"></param>
  /// <returns></returns>
  private static uint MAKELONG(ushort bLow,ushort bHigh)
  {
   return ((uint) (((ushort) (bLow)) | ((uint) ((ushort) (bHigh))) << 16));
  }
  
  #endregion
 }
}


您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think>我们需要判断两个IP地址(以CIDR形式表示,即IP地址/前缀长度)是否冲突(即是否有重叠的地址范围)。 思路: 1. 将CIDR字符串分解为IP地址和前缀长度。 2. 将IP地址转换为32位整数(假设IPv4)。 3. 根据前缀长度计算网络地址(即该CIDR代表的地址范围的起始地址)和广播地址(即结束地址)。 网络地址 = IP地址与子网掩码(由前缀长度算出)的按位与。 广播地址 = 网络地址 | (0xFFFFFFFF >> 前缀长度) 4. 对于两个CIDR,分别计算出网络地址和广播地址,然后判断两个区间是否有重叠。 判断重叠:如果第一个区间的结束(广播地址)小于第二个区间的开始(网络地址)者第一个区间的开始大于第二个区间的结束,则没有重叠,否则冲突。 注意:CIDR表示法中,前缀长度n,那么子网掩码是32位中前n位为1,后32-n位为0。在计算时,我们可以通过将0xFFFFFFFF左移(32-n)位再右移32-n位(者直接右移n位)来得到?但要注意,在C中,无符号整数的移位操作是逻辑移位。我们可以这样计算掩码:mask = (0xFFFFFFFFU << (32 - n)) & 0xFFFFFFFFU; 但实际上,更简单的是:mask = (0xFFFFFFFFU >> n) << n; 但这样对于n=0时,移位操作可能会超出32位,所以使用无符号长整型(32位以上)更好。 然而,我们也可以这样:先定义一个32位的掩码,如果n为0,则掩码为0;否则,掩码为 ~((1 << (32-n)) - 1) 然后取低32位。但为了避免溢出,我们可以用无符号长整型(如uint32_t)来处理。 步骤: a. 解析CIDR字符串:例如 "192.168.1.0/24" b. 将IP地址部分(点分十进制)转换为32位无符号整数。 c. 计算网络地址:ip_int & mask d. 计算广播地址:网络地址 | (~mask) (注意mask是32位,所以~mask也要限制在32位,可以用0xFFFFFFFFU进行与操作,者使用uint32_t类型) 5. 比较两个CIDR的地址范围是否有重叠: 第一个CIDR的范围: [net1, broadcast1] 第二个CIDR的范围: [net2, broadcast2] 冲突条件: (net1 <= broadcast2) && (net2 <= broadcast1) (注意:这里要求两个区间有重叠) 注意:网络地址和广播地址都是32位无符号整数,可以直接比较。 因此,我们需要编写以下函数: - 解析CIDR字符串,得到IP字符串和前缀长度(整数)。 - 将点分十进制IP字符串转换为32位整数。 - 计算网络地址和广播地址。 - 判断两个CIDR是否冲突。 由于问题要求C代码,我们将编写一个完整的示例。 注意:输入的两个CIDR字符串,我们假设是合法的,但代码中需要做简单的解析。 示例输入: cidr1 = "192.168.1.0/24" cidr2 = "192.168.1.128/25" 输出:冲突(因为192.168.1.0/24的范围是192.168.1.0到192.168.1.255,而192.168.1.128/25的范围是192.168.1.128到192.168.1.255,有重叠) 我们编写一个函数:int isConflict(const char *cidr1, const char *cidr2); 返回1表示冲突,0表示不冲突。 步骤: 1. 解析每个CIDR字符串,分离IP部分和前缀部分。 2. 将IP字符串转换为32位整数(按大端序,因为IP地址是高位在前,但我们的转换不需要考虑大小端,因为我们是按字节解析,然后移位组合成一个32位整数,这个整数在内存中的表示是小端,但我们在整数上操作,比较时是数值比较,所以没问题)。 3. 计算每个CIDR的网络地址和广播地址。 4. 判断两个区间是否有重叠。 解析CIDR字符串:找到'/'字符,将其分为两部分。 转换IP字符串为整数:使用sscanf者自己解析。 这里我们使用sscanf来解析IP地址的四个部分。 注意:CIDR字符串可能没有空格。 代码实现: 由于我们只关心逻辑,所以编写一个函数来解析CIDR字符串。 我们将编写以下辅助函数: - 解析一个CIDR字符串,返回网络地址和广播地址(者存储在两个变量中)。 - 然后比较。 考虑到简洁性,我们将编写一个函数:void parse_cidr(const char *cidr, uint32_t *network, uint32_t *broadcast); 在这个函数中,我们解析CIDR,然后计算出网络地址和广播地址。 然后,在isConflict函数中调用parse_cidr两次,然后判断两个区间是否重叠。 重叠判断(net1 <= broadcast2) && (net2 <= broadcast1) 注意:网络地址和广播地址都是32位无符号整数,所以可以直接比较。 下面我们写代码。注意包含必要的头文件。 注意:我们假设输入是合法的IPv4 CIDR。 代码示例: </think> 以下是判断两个 CIDR 格式(IP/前缀)IP 地址是否冲突的 C 代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> // 将点分十进制IP转换为32位整数 uint32_t ip_to_uint(const char *ip) { uint8_t bytes[4]; sscanf(ip, "%hhu.%hhu.%hhu.%hhu", &bytes[3], &bytes[2], &bytes[1], &bytes[0]); return ((uint32_t)bytes[3] << 24) | ((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[1] << 8) | bytes[0]; } // 解析CIDR格式,返回网络地址和广播地址 void parse_cidr(const char *cidr, uint32_t *network, uint32_t *broadcast) { char ip_str[20]; int prefix; sscanf(cidr, "%19[^/]/%d", ip_str, &prefix); uint32_t ip = ip_to_uint(ip_str); uint32_t mask = prefix ? (0xFFFFFFFFU << (32 - prefix)) : 0; *network = ip & mask; *broadcast = *network | (0xFFFFFFFFU >> prefix); } // 判断两个CIDR是否冲突 int is_conflict(const char *cidr1, const char *cidr2) { uint32_t net1, bc1, net2, bc2; parse_cidr(cidr1, &net1, &bc1); parse_cidr(cidr2, &net2, &bc2); return (net1 <= bc2 && net2 <= bc1) ? 1 : 0; } // 测试用例 int main() { const char *cidr1 = "192.168.1.0/24"; const char *cidr2 = "192.168.1.128/25"; printf("CIDR1: %s\nCIDR2: %s\n冲突: %s\n", cidr1, cidr2, is_conflict(cidr1, cidr2) ? "是" : "否"); return 0; } ``` ### 代码说明: 1. **ip_to_uint()**:将点分十进制IP转换为32位无符号整数(小端序) 2. **parse_cidr()**:解析CIDR格式,计算网络地址和广播地址 3. **is_conflict()**:通过比较地址范围判断冲突 - 冲突条件:`(net1 <= broadcast2) && (net2 <= broadcast1)` 4. **示例测试**: - `192.168.1.0/24`(范围:0-255) - `192.168.1.128/25`(范围:128-255) - 结果:存在冲突(输出"是")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值