1

大家好,我正在寻找一种更好的解决方案来检查/计算 IP 地址是否与您的 iPhone 位于同一子网中。

背景:我正在通过 Zeroconf / Bonjour 查找设备,这些设备可以有多个 IP 地址。所以我想检查我的设备可以访问其中哪些。我认为最简单的方法是获取外部 IP 并将其与我的子网掩码连接,但我还没有找到任何直接执行此操作的方法(需要两者都为 int),所以我做了一个解决方法。

编码:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <net/if.h>

-(void)netServiceDidResolveAddress:(NSNetService *)service {
  NSLog(@" # # # Bonjour.netServiceDidResolveAddress # # # ");
  self.isConnected = YES;
  self.connectedService = service;

  NSLog(@"service.hostName   : %@", service.hostName);
  NSLog(@"service.name       : %@", service.name);
  NSLog(@"service.description: %@", service.description);

  // # # #

  // get MAC-ADDR from TXTRecordData
  NSData *txtRecord = service.TXTRecordData;

  unsigned char aBuffer[[txtRecord length]];
  [txtRecord getBytes:aBuffer length:[txtRecord length]];
  NSString *macAddr = [NSString stringWithCString:(const char *)aBuffer encoding:NSStringEncodingConversionAllowLossy];
  if(macAddr && macAddr.length >28)
  {
      macAddr = [macAddr substringFromIndex:12];
      macAddr = [macAddr substringToIndex:17];
  }

  NSLog(@"service.macAddr: %@", macAddr);
  // # # #

  NSString           *name = nil;
  NSData             *address = nil;
  struct sockaddr_in *socketAddress = nil;
  NSString           *ipString = nil;
  int       port;
  int   i = 0;

  for (i = 0; i < [[service addresses] count]; i++)
  {
      NSString *ip;
      name = [service name];
      address = [[service addresses] objectAtIndex:i];
      socketAddress = (struct sockaddr_in *)[address bytes];
      ip = [NSString stringWithFormat: @"%s", inet_ntoa (socketAddress->sin_addr)];

      if([ip isEqualToString:@"0.0.0.0"])
          continue;

      NSLog(@"- - - ");
      if([self isIpInSubnet:ip])
      {
          ipString = [ip copy];
          port = service.port;
          NSLog(@"set IP");
      }
      NSLog(@"%@", ipString);
      NSLog(@"%d", port);
 }
....
}

-

- (BOOL)isIpInSubnet:(NSString *)targetIP{
// http://www.cocoabuilder.com/archive/cocoa/127230-finding-subnet.html
// http://veys.com/

struct ifaddrs *ifap, *ifp;
char    ip[NI_MAXHOST], nm[NI_MAXHOST];
BOOL isInMask = NO;

if(getifaddrs(&ifap) < 0)
    perror("getifaddrs");

for(ifp = ifap; ifp; ifp = ifp->ifa_next) {
    /* Ignore everything but IPv4 */
    if(ifp->ifa_addr->sa_family != AF_INET )
        continue;

    /* Ignore interfaces marked down. */
    if(!(ifp->ifa_flags & IFF_UP))
        continue;

    /* Ignore interfaces without netmask. */
    if(!ifp->ifa_netmask)
        continue;

    if(getnameinfo(ifp->ifa_addr, ifp->ifa_addr->sa_len, ip, sizeof(ip),
                   NULL, 0, NI_NUMERICHOST) != 0)
        perror("getnameinfo");

    if(getnameinfo(ifp->ifa_netmask, ifp->ifa_netmask->sa_len, nm,
                   sizeof(nm), NULL, 0, NI_NUMERICHOST) != 0)
        perror("getnameinfo");

    /* Ignore interfaces for localhost. */
    if([[NSString stringWithFormat:@"%s", ip] isEqualToString:@"127.0.0.1"])
        continue;

    // # # # # # # # # # # # #

    NSArray *ipChunks = [targetIP componentsSeparatedByString:@"."]; // chunks for extern IP
    NSArray *nmChunks = [[NSString stringWithFormat:@"%s",nm] componentsSeparatedByString:@"."];

    NSUInteger ipRaw = 0;
    NSUInteger nmRaw = 0;
    NSUInteger shift = 24;
    for (NSUInteger i = 0; i < 4; ++i, shift -= 8) {
        ipRaw |= [[ipChunks objectAtIndex:i] intValue] << shift;
        nmRaw |= [[nmChunks objectAtIndex:i] intValue] << shift;
    }

    NSUInteger bcRaw = nmRaw & ipRaw; // lowest interface addr.
    NSString *nw1 = [NSString stringWithFormat:@"%d.%d.%d.%d", (bcRaw & 0xFF000000) >> 24,
                     (bcRaw & 0x00FF0000) >> 16, (bcRaw & 0x0000FF00) >> 8, bcRaw & 0x000000FF];

    ipRaw = nmRaw = 0;
    shift = 24;

    ipChunks = [[NSString stringWithFormat:@"%s",ip] componentsSeparatedByString:@"."]; // chunks for local IP

    for (NSUInteger i = 0; i < 4; ++i, shift -= 8) {
        ipRaw |= [[ipChunks objectAtIndex:i] intValue] << shift;
        nmRaw |= [[nmChunks objectAtIndex:i] intValue] << shift;
    }

    bcRaw = nmRaw & ipRaw;
    NSString *nw2 = [NSString stringWithFormat:@"%d.%d.%d.%d", (bcRaw & 0xFF000000) >> 24,
                     (bcRaw & 0x00FF0000) >> 16, (bcRaw & 0x0000FF00) >> 8, bcRaw & 0x000000FF];

    isInMask = [nw1 isEqualToString:nw2];
    NSLog(@"intern: %@ - extern: %@", nw2, nw1);
    // # # # # # # # # # # # #

    NSLog(@"ip %@ is in range with %s in mask %s ? %@", targetIP, ip, nm, isInMask ? @"YES" : @"NO");
}
// Free memory 
freeifaddrs(ifap);

return isInMask;
}

如果有人暗示要让它变得更容易或更好,总是欢迎他发布他的解决方案:)

4

0 回答 0