IOS获取IP地址详解

上书提到小编自制Demo中引进了一个新的技术--获取IP地址(源码来源于网上),由此本回将对于上文提及的代码做以详尽的分析,如果有更好的理解方式或者建议,可在评论区或私聊与小编进行探讨~更好的文章可以投稿专题 更多内容收录专题

https://www.jianshu.com/c/ec6bd31fdbe1

源码
//Get IP Address
- (NSString *)getIPAddress{
    NSString *adress = @"error"; 
    struct ifaddrs *interfaces = NULL; 
    struct ifaddrs *temp_addr = NULL; 
    int success = 0; 

    success = getifaddrs(&interfaces); 
    if (success == 0) {
        temp_addr = interfaces; //将结构体复制给副本temp_addr
        while (temp_addr != NULL) {
          
            if (temp_addr->ifa_addr->sa_family == AF_INET) {
                //check if interface is en0 which is the wifi conection on the iphone
                if ([[NSString stringWithUTF8String:temp_addr ->ifa_name] isEqualToString:@"en0"]) {
                    adress = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];

                }
            }
            temp_addr = temp_addr -> ifa_next;
        }
    }
    
    //Free memory
    //extern void freeifaddrs(struct ifaddrs *);
    freeifaddrs(interfaces);
    return (adress);
}

重点强调:在实现获取IP地址代码的最初工作是先导入相关的头文件

#import <ifaddrs.h>
#import <arpa/inet.h>

分析:

  • (NSString *)getIPAddress{......}
因为我们的目的是将IP地址返回后并且传送给UILabel标签从而改变Label.text的内容(参考上一章节的UILabel *getIPLabel)
所以,返回值设置为NSString类型,返回字符串类型,并由标签接收
  • NSString *adress = @"error";
我们先设置一个目标参考量,利用字符串类型的对象adress来作为IP地址的返回值,其中我们先设定返回地址为error,或者你可以自己定义NSString *adress = @“error of the IP address and I can return it.”;
  • struct ifaddrs *interfaces = NULL; struct ifaddrs *temp_addr = NULL;
    在这两部分我们设置了两个结构体变量interfaces and temp_addr为NULL;
我们先来看一下这两个C结构体的本体
struct ifaddrs{
  struct ifaddrs *ifa_next; //Next item in list
  char * ifa_name; //Name of interface
  unsigned int ifa_flags; //Flags from SIOCGIFFLAGS
  struct sockaddr * ifa_addr;  //Address if interface
  struct sockaddr * ifa_netmask; //Netmask of interface
  union{
      struct sockaddr * ifu_broadaddr; //Broadcast address of interface
      struct sockaddr * ifu_dstaddr; //point-to-point destination address
  }ifa_ifu;
  #define ifa_broadaddr ifa_ifu.ifu_broadaddr
  #define ifa_dstaddr if_a_ifu.ifu_dstaddr
  void *ifa_data; //Address-specific data
};
讲解部分

1.ifa_next:指向链表的下一个成员;【链表:链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的】
2.ifa_name: 是接口的名称,以0结尾的字符串,比如eth0,10;
3.ifa_flags: 是接口的标识符;
4.ifa_netmask: 存储该接口的子网掩码;
5.结构体变量存储广播地址或者对点地址
6.ifa_data: 存储了该接口协议族的特殊信息,通常是NULL;

深度剖析

ifa_name

#define IOS_CELLULAR @"pdop_ip0":
#define IOS_WIFI @"en0";
#define IOS_VPN @"utun0";
#define IP_ADDR_IPV4 @"ipv4";
#define IP_ADDR_IPV6 @"ipv6";
因此,在内部判断时候将字符串以UTF8格式读取,temp_addr-->interfaces,利用结构体指针的的指向运算符指向结构体中的ifa_name,来获取接口的名称(WIFI链接状态下),如果WIFI断开则失效,返回值为false。
同样,使用上述宏定义可以判断不同设备状态下获取的地址
 if ([[NSString stringWithUTF8String:temp_addr ->ifa_name] isEqualToString:@"en0"]) {
                    adress = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];

                }

观察代码不难分析出, [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]将返回的值赋给了adress,可inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr是什么意思,我们继续来看,先返回success部分讲解。

getifaddrs()函数
int success = 0; 

    success = getifaddrs(&interfaces); 
在这里我们定义了一个整形变量success并给了初始化的数值为0,下一行调用了getifaddrs()函数,并且将返回值赋予了success。
定义:函数getifaddrs(int getifaddrs(struct ifaddrs **_ifap))
作用:获取本地网络接口信息,将存储在链表中,链表头结点指针存储于_ifap中带回,函数执行成功返回值为0,失败返回值为-1

此时,如果getifaddrs()成功的获取了本地网络接口的信息时候,则success被赋予0

if (temp_addr->ifa_addr->sa_family == AF_INET) {......}
当中的temp_addr是结构体ifaddrs指针,利用指针运算符取出成员变量ifa_addr结构体(定义如下代码)来获取网络的接口
struct sockaddr{
    _uint8_t sa_len; //total length
    sa_family_t sa_family; //address family
    char sa_data[14]; //actually larger
    #define AF_INET 2  
}
其中,面向网络的套接字的家族名为 AF_INET,其地址是主机--端口
例如:套接字-->电话接口 那么 主机或端口-->号码

重头戏 “sockaddr_in”

[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];

此处,我们将temp_addr强制转换为结构体sockaddr_in类型,这个是套接字的返回类型,使得temp_addr指向ifa_addr的sin_addr

   struct sockaddr_in {
                       __uint8_t    sin_len;
                        sa_family_t    sin_family;
                       in_port_t    sin_port;
                        struct    in_addr sin_addr;
                       char        sin_zero[8];
                   };
而结构体 in_addr sin_addr将返回地址给adress

重要部分完成后,继续传递下一个链表知道范围为空链表为止

 temp_addr = temp_addr -> ifa_next;

最后,切记将指针所分配的内存释放掉

//Free memory
    //extern void freeifaddrs(struct ifaddrs *);
    freeifaddrs(interfaces);
好啦,今天的文章到这也就结束,小编通过各人搜集,将各个部分整理在了一起,希望能为大家提供帮助哦,从下一回开始,我们继续空间选择器的介绍以及更多Demo的引入,谢谢大家支持!!!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 代码中到处都需要命名。作为程序员,我们得给类命名,给变量命名,给函数命名,给参数命名,给命名空间命名,等等等等。下...
    流哲羽阅读 1,605评论 1 5
  • 今天是周日(大寒) 起床:6:45 就寝:22:30 天气:大雨 心情:一般 纪念日:无 任务清单 昨日完成的任务...
    三七木木阅读 83评论 0 0
  • “你怎么那么喜欢看《悲惨世界》?”朋友笑道。“《悲惨世界》其实并不悲惨!”我脱口而出。对于己所言,我自己也半信半疑...
    笑若叶子阅读 408评论 0 3
  • 朔方雪舞天地中, 喜把春秋当作冬。 银装层层尽呵护, 可怜南国无雪拥。
    点点可可阅读 298评论 0 4