大家好,我正在寻找一种更好的解决方案来检查/计算 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;
}
如果有人暗示要让它变得更容易或更好,总是欢迎他发布他的解决方案:)