Bir iphone'un MAC adresini programlı olarak nasıl alabilirim


144

Bir iPhone'un MAC adresini ve IP adresini programlı olarak nasıl alabilirim?


bir iPhone uygulamasında MAC adresini ve IP adresini programlı olarak almak istiyorum.

Kablosuz MAC adresi? veya BlueTooth? Birçok Mac adresi var.
mskw

11
İOS 7'den başlayarak 02:00:00:00:00:00, herhangi bir cihazda MAC adresi istediğinde sistem her zaman değeri döndürür . Cevabımı aşağıdan kontrol edin.
Hejazi

IOS ve üzeri (bugüne kadar) için stackoverflow.com/questions/11836225/…
rptwsthi

Yanıtlar:


114

NOT iOS7'den itibaren artık cihaz MAC adreslerini alamazsınız. Gerçek MAC yerine sabit bir değer döndürülecektir


Bir süre önce tökezlediğim bir şey. Başlangıçta buradan biraz değiştirdim ve işleri temizledim.

IPAdresi.h
IPAdresi.c

Ve kullanmak için

InitAddresses();
GetIPAddresses();
GetHWAddresses();

int i;
NSString *deviceIP = nil;
for (i=0; i<MAXADDRS; ++i)
{
    static unsigned long localHost = 0x7F000001;        // 127.0.0.1
    unsigned long theAddr;

    theAddr = ip_addrs[i];

    if (theAddr == 0) break;
    if (theAddr == localHost) continue;

    NSLog(@"Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);

        //decided what adapter you want details for
    if (strncmp(if_names[i], "en", 2) == 0)
    {
        NSLog(@"Adapter en has a IP of %s", ip_names[i]);
    }
}

Adaptör adları simülatöre / cihaza ve cihazdaki wifi veya hücreye bağlı olarak değişir.


Ben sadece bu herhangi bir genel OS X yaklaşımından farklı olup olmadığını merak ediyorum (ben bir mac n00b çünkü soruyorum)
Tamas Czinege 24:09

2
@abc: Bununla ilgili başka bir soru göndermenizi tavsiye ederim. Farklı bir soru için yorumlara gömmekten daha iyi olun.
PyjamaSam

1
ama ether_ntoa'ya ne demeli? bu özel API değil mi?
stigi

1
@NicTesla Ben kesin yorum yapamam, ama sadece temel ağ aramaları yapıyor beri bir sorun göremiyorum. Bununla birlikte, mac adresini almak ve bir çeşit alternatif benzersiz tanımlayıcı geliştirmek için UDID'nin iOS5'ten kaldırılmasıyla söylenmesi, gelecekte bir noktada elma tarafından incelenebilir.
PyjamaSam

1
ether_ntoaUyarı ile ilgili olarak ,
adrese göz atın

45

Güncelleme: bu iOS 7'de çalışmaz . ASIdentifierManager kullanmalısınız .


MobileDeveloperTips web sitesinde daha temiz bir çözüm :

#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

...

- (NSString *)getMacAddress
{
  int                 mgmtInfoBase[6];
  char                *msgBuffer = NULL;
  size_t              length;
  unsigned char       macAddress[6];
  struct if_msghdr    *interfaceMsgStruct;
  struct sockaddr_dl  *socketStruct;
  NSString            *errorFlag = NULL;

  // Setup the management Information Base (mib)
  mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
  mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
  mgmtInfoBase[2] = 0;              
  mgmtInfoBase[3] = AF_LINK;        // Request link layer information
  mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces

  // With all configured interfaces requested, get handle index
  if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0) 
    errorFlag = @"if_nametoindex failure";
  else
  {
    // Get the size of the data available (store in len)
    if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0) 
      errorFlag = @"sysctl mgmtInfoBase failure";
    else
    {
      // Alloc memory based on above call
      if ((msgBuffer = malloc(length)) == NULL)
        errorFlag = @"buffer allocation failure";
      else
      {
        // Get system information, store in buffer
        if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
          errorFlag = @"sysctl msgBuffer failure";
      }
    }
  }

  // Befor going any further...
  if (errorFlag != NULL)
  {
    NSLog(@"Error: %@", errorFlag);
    return errorFlag;
  }

  // Map msgbuffer to interface message structure
  interfaceMsgStruct = (struct if_msghdr *) msgBuffer;

  // Map to link-level socket structure
  socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);

  // Copy link layer address data in socket structure to an array
  memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);

  // Read from char array into a string object, into traditional Mac address format
  NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                                macAddress[0], macAddress[1], macAddress[2], 
                                macAddress[3], macAddress[4], macAddress[5]];
  NSLog(@"Mac Address: %@", macAddressString);

  // Release the buffer memory
  free(msgBuffer);

  return macAddressString;
}

bağlantıyı iphonedevelopertips yerine mobiledevelopertips olarak değiştirin
SEG

Apple'ın iOS7'de bunu kırması ÇOK olası ... ve resmi Apple Dev Forumları dışında gönderilinceye kadar bu konuda herkese açık yorum yapamayacağız.
Gabe

3
Bu, iOS7 ile iPhone5'imde işe yaramadı. Bana doğru değil 02: 00: 00: 00: 00: 00 verir.
Sjoerd Perfors

3
@Brenden Artık iOS7'de PublicAPI kullanarak ağ MAC adresi alamıyorsunuz. Benzersiz bir kimliğe ihtiyacınız varsa, kullanmalısınızIdentifierManager
ArtFeel

2
@SjoerdPerfors iOS 7'de gerçekten de 02:00:00:00:00:00Apple'ın gizlilik önlemiyle aynı adresten daha fazlasını alacaksınız .
Basil Bourque

31

Wifi etkin olsun ya da olmasın adresi döndürmek için bir şey istedim, bu yüzden seçilen çözüm benim için çalışmadı. Bazı tweaking sonra bazı forumda buldum başka bir çağrı kullandım. Aşağıdaki ile sona erdi (paslı C benim mazeret):

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>


char*  getMacAddress(char* macAddress, char* ifName) {

int  success;
struct ifaddrs * addrs;
struct ifaddrs * cursor;
const struct sockaddr_dl * dlAddr;
const unsigned char* base;
int i;

success = getifaddrs(&addrs) == 0;
if (success) {
    cursor = addrs;
    while (cursor != 0) {
        if ( (cursor->ifa_addr->sa_family == AF_LINK)
            && (((const struct sockaddr_dl *) cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp(ifName,  cursor->ifa_name)==0 ) {
            dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
            base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
            strcpy(macAddress, ""); 
            for (i = 0; i < dlAddr->sdl_alen; i++) {
                if (i != 0) {
                    strcat(macAddress, ":");
                }
                char partialAddr[3];
                sprintf(partialAddr, "%02X", base[i]);
                strcat(macAddress, partialAddr);

            }
        }
        cursor = cursor->ifa_next;
    }

    freeifaddrs(addrs);
}    
return macAddress;
}

Ve sonra ben aşağıdaki gibi en0 istiyor diyebilirim :

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
                                              encoding:NSMacOSRomanStringEncoding];
free(macAddressString);

9
#Define eklemek zorunda kaldım IFT_ETHER 0x6
teedyay

Bu benim için işe yaramıyor ... ifName ve macaddress değişkeni bildirilmedi diyor.
bugfixr

Yukarıdaki arama kodu sızacaktır. serbest (macAddressString); Yukarıdaki çağrı yönteminden dönmeden önce. Ayrıca, yukarıdaki arama kodu başka bir yöntemdeyse macAddress otomatik olarak başlatılmalıdır.

4
Açıkça söylemek gerekirse, kodun kendisi sızmayacak, yorumcu sonunda arama parçacığı hakkında konuşuyordu, burada onları serbest bırakmadan iki dize tahsis ettim.
Gemi sorumlusu

1
Bunu güzel bir objektif-c yöntemine koydum ve hiçbir parametre gerektirmediği için yaptım: gist.github.com/wsidell/5069159
wsidell

23

İOS 7'den başlayarak 02:00:00:00:00:00, herhangi bir cihazda MAC adresi istediğinde sistem her zaman değeri döndürür .

İOS 7 ve sonrasında, bir iOS aygıtının MAC adresini sorarsanız, sistem 02: 00: 00: 00: 00: 00 değerini döndürür. Aygıtı tanımlamanız gerekiyorsa, bunun yerine UIDevice'nin tanımlayıcıForVendor özelliğini kullanın. (Kendi reklam amaçları için tanımlayıcıya ihtiyaç duyan uygulamalar bunun yerine ASIdentifierManager'ın AdvertisingIdentifier özelliğini kullanmayı düşünmelidir.) "

Referans: releasenotes


API'daki bu kullanımdan çıkarma hakkında gerçekten güzel olan şey, simülatörde hala doğru ve sadece şu anda donanımda çalışmasıdır.
John Nye

12

Bu konuda çeşitli çözümler var, ama bir şey bulamadım. Bu yüzden kendi çözümümü yaptım:

nicinfo

Nasıl kullanılır :

NICInfoSummary* summary = [[[NICInfoSummary alloc] init] autorelease];

// en0 is for WiFi 
NICInfo* wifi_info = [summary findNICInfo:@"en0"];

// you can get mac address in 'XX-XX-XX-XX-XX-XX' form
NSString* mac_address = [wifi_info getMacAddressWithSeparator:@"-"];

// ip can be multiple
if(wifi_info.nicIPInfos.count > 0)
{
    NICIPInfo* ip_info = [wifi_info.nicIPInfos objectAtIndex:0];
    NSString* ip = ip_info.ip;
    NSString* netmask = ip_info.netmask;
    NSString* broadcast_ip = ip_info.broadcastIP;
}
else
{
    NSLog(@"WiFi not connected!");
}

Çok güzel ve kullanışlı bir sınıf! İyi iş! Ancak, her iki sınıfta da [super dealloc] 'u kaçırdınız ve xCode'da uyarılara yol açan bir kitaplık eklemeyi unuttunuz. Yamalı
Raptor

bu sonucu almak Mac Adres: 02: 00: 00: 00: 00: 00
Stalin Pusparaj

1
Evet. Apple, iOS 7'den beri bunu engelledi :( ... developer.apple.com/library/content/releasenotes/General/…
Kenial

5

Bu oldukça temiz bir çözüm gibi görünüyor: UIDevice BIdentifier

// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (NSString *) macaddress{

    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        free(buf);
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", 
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);

    return outstring;
}

1
Çözümünüzü kullanıyorum,% 99 vakalar beklendiği gibi çalışıyor, ancak% 1 oran Mac adresini alamıyor, NULL döndürüyor, AppStore'daki kullanıcılar tarafından bildiriliyor. Hala tekrarlanabilir adımlar alamıyorum, anladınız mı? Teşekkür ederim.
jianhua

Henüz herhangi bir sorun fark etmedim, ama bir göz atacağım!
Grantland

@ Jianhua'nın yorumunu takip ederek: uygulamayı kullanamayan bir kullanıcıdan rapor aldık, çünkü bu kod cihazı için null döndürüyor (her sunucu çağrısının kimliğini doğrulamak için tanımlayıcıyı kullanıyoruz).
samvermette

Başarısız vaka IOS sürüm 5.0.1 ile iPhone 4S'de, elbette sadece bazı özel durumlarda.
jianhua

5

Şimdi iOS 7 cihazları - her zaman 02: 00: 00: 00: 00: 00 MAC adresini döndürüyor.

Bu yüzden daha iyi [UIDevice identifierForVendor] kullanın.

uygulamaya özgü benzersiz anahtar elde etmek için bu yöntemi çağırmak daha iyidir

Kategori daha uygun olacak

"UIDevice + Identifier.h" dosyasını içe aktarın

- (NSString *) identifierForVendor1
{
    if ([[UIDevice currentDevice] respondsToSelector:@selector(identifierForVendor)]) {
        return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    }
    return @"";
}

Şimdi benzersiz adres almak için yukarıdaki yöntemi arayın

NSString *like_UDID=[NSString stringWithFormat:@"%@",
                [[UIDevice currentDevice] identifierForVendor1]];

NSLog(@"%@",like_UDID);

bu tanımlayıcı, aynı uygulamanın birden çok yüklemesinde cihaz başına tutarlı mıdır?
samsam

4

@Grantland Bu "oldukça temiz çözüm", iPhoneDeveloperTips çözümü üzerindeki kendi geliştirmeme benziyor.

Adımımı burada görebilirsiniz: https://gist.github.com/1409855/

/* Original source code courtesy John from iOSDeveloperTips.com */

#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

+ (NSString *)getMacAddress
{
    int                 mgmtInfoBase[6];
    char                *msgBuffer = NULL;
    NSString            *errorFlag = NULL;
    size_t              length;

    // Setup the management Information Base (mib)
    mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
    mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
    mgmtInfoBase[2] = 0;              
    mgmtInfoBase[3] = AF_LINK;        // Request link layer information
    mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces

    // With all configured interfaces requested, get handle index
    if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0) 
        errorFlag = @"if_nametoindex failure";
    // Get the size of the data available (store in len)
    else if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0) 
        errorFlag = @"sysctl mgmtInfoBase failure";
    // Alloc memory based on above call
    else if ((msgBuffer = malloc(length)) == NULL)
        errorFlag = @"buffer allocation failure";
    // Get system information, store in buffer
    else if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
    {
        free(msgBuffer);
        errorFlag = @"sysctl msgBuffer failure";
    }
    else
    {
        // Map msgbuffer to interface message structure
        struct if_msghdr *interfaceMsgStruct = (struct if_msghdr *) msgBuffer;

        // Map to link-level socket structure
        struct sockaddr_dl *socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);

        // Copy link layer address data in socket structure to an array
        unsigned char macAddress[6];
        memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);

        // Read from char array into a string object, into traditional Mac address format
        NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
                                      macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]];
        NSLog(@"Mac Address: %@", macAddressString);

        // Release the buffer memory
        free(msgBuffer);

        return macAddressString;
    }

    // Error...
    NSLog(@"Error: %@", errorFlag);

    return nil;
}

ve neden kendi cevaplarıma yorum ekleyebileceğimi anlamıyorum ama başkalarının cevaplarına değil? : /
Marur

1
Çünkü itibarınız yeterince yüksek değil.
honus

Teşekkürler, birkaç kişi bu çözümün kendi varyantlarını bulmuş
josh-fuggle

1

Artık iOS 7.0 veya üstünü çalıştıran cihazlarda mümkün değil , bu nedenle Swift'te MAC adresi almak mümkün değil .

Apple'ın belirttiği gibi:

İOS 7 ve sonrasında, bir iOS aygıtının MAC adresini sorarsanız, sistem 02: 00: 00: 00: 00: 00 değerini döndürür. Aygıtı tanımlamanız gerekiyorsa, bunun yerine UIDevice'nin tanımlayıcıForVendor özelliğini kullanın. (Kendi reklam amaçları için tanımlayıcıya ihtiyaç duyan uygulamalar, bunun yerine ASIdentifierManager'ın AdvertisingIdentifier özelliğini kullanmayı düşünmelidir.)


0
#import <sys/socket.h>
#import <net/if_dl.h>
#import <ifaddrs.h>
#import <sys/xattr.h>
#define IFT_ETHER 0x6

...

- (NSString*)macAddress
{
    NSString* result = nil;

    char* macAddressString = (char*)malloc(18);
    if (macAddressString != NULL)
    {
        strcpy(macAddressString, "");

        struct ifaddrs* addrs = NULL;
        struct ifaddrs* cursor;

        if (getifaddrs(&addrs) == 0)
        {
            cursor = addrs;

            while (cursor != NULL)
            {
                if ((cursor->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl*)cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp("en0", cursor->ifa_name) == 0)
                {
                    const struct sockaddr_dl* dlAddr = (const struct sockaddr_dl*) cursor->ifa_addr;
                    const unsigned char* base = (const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];

                    for (NSInteger index = 0; index < dlAddr->sdl_alen; index++)
                    {
                        char partialAddr[3];

                        sprintf(partialAddr, "%02X", base[index]);
                        strcat(macAddressString, partialAddr);
                    }
                }

                cursor = cursor->ifa_next;
            }

        }

        result = [[[NSString alloc] initWithUTF8String:macAddressString] autorelease];

        free(macAddressString);
    }

    return result;
}

0

İOS 6'da cihazın benzersiz tanımlayıcısını temel alan bir uniqueString oluşturmak için:

#import <AdSupport/ASIdentifierManager.h>

NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"uniqueString: %@", uniqueString);

1
bunun sorulan soru ile nasıl bir ilişkisi var?
Valeriy Van

1
Çoğu durumda cihazı benzersiz bir şekilde tanımlamak için Mac adresi gerekir. Bunun yerine, bu çözümü kullanabilirsiniz.
Denis Kutlubaev

0

Bu soruların çoğu yalnızca Mac adresine yöneliktir. IP adresine de ihtiyacınız varsa, bunu yazdım, biraz çalışmaya ihtiyacınız olabilir, ancak makinemde iyi çalışıyor gibi görünüyor ...

- (NSString *)getLocalIPAddress
{
    NSArray *ipAddresses = [[NSHost currentHost] addresses];
    NSArray *sortedIPAddresses = [ipAddresses sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    numberFormatter.allowsFloats = NO;

    for (NSString *potentialIPAddress in sortedIPAddresses)
    {
        if ([potentialIPAddress isEqualToString:@"127.0.0.1"]) {
            continue;
        }

        NSArray *ipParts = [potentialIPAddress componentsSeparatedByString:@"."];

        BOOL isMatch = YES;

        for (NSString *ipPart in ipParts) {
            if (![numberFormatter numberFromString:ipPart]) {
                isMatch = NO;
                break;
            }
        }
        if (isMatch) {
            return potentialIPAddress;
        }
    }

    // No IP found
    return @"?.?.?.?";
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.