Nikolay Shubenkov
Nikolay Shubenkov

Reputation: 3243

iOS. get other device/computer name by IP in the same local network

One task of my program is to scan local wi-fi network for any devices/computers in same network. I found solution to get all working devices IPs, but did not managed to get names of them. I did not find any clue to solve this problem. Any suggestions?

Upvotes: 6

Views: 2557

Answers (3)

Aaban Tariq Murtaza
Aaban Tariq Murtaza

Reputation: 1252

Swift Edition of @neilco answer.

class HostnameConverter {
    
    static func hostnames(forIPv4Address address: String) -> [String]? {
        var result: UnsafeMutablePointer<addrinfo>?
        var hints = addrinfo()
        memset(&hints, 0, MemoryLayout.size(ofValue: hints))
        hints.ai_flags = AI_NUMERICHOST
        hints.ai_family = PF_UNSPEC
        hints.ai_socktype = SOCK_STREAM
        hints.ai_protocol = 0
        
        let errorStatus = getaddrinfo(address, nil, &hints, &result)
        guard errorStatus == 0 else {
            return nil
        }
        defer {
            freeaddrinfo(result)
        }
        
        guard let ai_addr = result?.pointee.ai_addr,
              let ai_addrlen = result?.pointee.ai_addrlen,
              let addressRef = CFDataCreate(nil, ai_addr, numericCast(ai_addrlen))
        else {
            return nil
        }
        
        let hostRef = CFHostCreateWithAddress(nil, addressRef)
        
        let succeeded = CFHostStartInfoResolution(hostRef.takeUnretainedValue(), .names, nil)
        guard succeeded else {
            return nil
        }
        
        var hostnames = [String]()
        if let hostnamesRef = CFHostGetNames(hostRef.takeUnretainedValue(), nil) {
            for currentIndex in 0..<CFArrayGetCount(hostnamesRef.takeUnretainedValue()) {
                let cfString = unsafeBitCast(CFArrayGetValueAtIndex(hostnamesRef.takeUnretainedValue(), currentIndex), to: CFString.self)
                let hostname = String(cfString)
                hostnames.append(hostname)
            }
        }
        
        return hostnames
    }
}

Upvotes: 0

carya.liu
carya.liu

Reputation: 51

BOOL succeeded = CFHostStartInfoResolution(hostRef, kCFHostNames, NULL); Now I encounter that always failed at this line, and I tried to use getnameinfo function, it is still can't get the hostname

Upvotes: 0

neilco
neilco

Reputation: 8012

In order to perform a reverse DNS lookup, you need to call the CFHostGetNames function, like this:

+ (NSArray *)hostnamesForIPv4Address:(NSString *)address
{
    struct addrinfo *result = NULL;
    struct addrinfo hints;

    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_NUMERICHOST;
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;

    int errorStatus = getaddrinfo([address cStringUsingEncoding:NSASCIIStringEncoding], NULL, &hints, &result);
    if (errorStatus != 0) {
        return nil;
    }

    CFDataRef addressRef = CFDataCreate(NULL, (UInt8 *)result->ai_addr, result->ai_addrlen);
    if (addressRef == nil) {
        return nil;
    }
    freeaddrinfo(result);

    CFHostRef hostRef = CFHostCreateWithAddress(kCFAllocatorDefault, addressRef);
    if (hostRef == nil) {
        return nil;
    }
    CFRelease(addressRef);

    BOOL succeeded = CFHostStartInfoResolution(hostRef, kCFHostNames, NULL);
    if (!succeeded) {
        return nil;
    }

    NSMutableArray *hostnames = [NSMutableArray array];

    CFArrayRef hostnamesRef = CFHostGetNames(hostRef, NULL);
    for (int currentIndex = 0; currentIndex < [(__bridge NSArray *)hostnamesRef count]; currentIndex++) {
        [hostnames addObject:[(__bridge NSArray *)hostnamesRef objectAtIndex:currentIndex]];
    }

    return hostnames;
}

Upvotes: 5

Related Questions