如何在iPhone上获取WIFI网关地址?

16

我需要获取iPhone连接的wifi网络的网关地址。有人知道如何获取吗?

只是想澄清一下,我正在寻找这个屏幕的信息:

enter image description here

谢谢。


一种技术,虽然可能有点专业化,但在这里概述:https://dev59.com/GkzSa4cB1Zd3GeqPjhlL - Paul Dixon
4个回答

14

route.h 文件从 http://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/route.h 添加到您的项目中。

创建 getgateway.h

int getdefaultgateway(in_addr_t * addr);

创建 getgateway.c

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include "getgateway.h"

#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
    #include <net/route.h>
    #define TypeEN    "en1"
#else
    #include "route.h"
    #define TypeEN    "en0"
#endif

#include <net/if.h>
#include <string.h>

#define CTL_NET         4               /* network, see socket.h */


#if defined(BSD) || defined(__APPLE__)

#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))

int getdefaultgateway(in_addr_t * addr)
{
    int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
        NET_RT_FLAGS, RTF_GATEWAY};
    size_t l;
    char * buf, * p;
    struct rt_msghdr * rt;
    struct sockaddr * sa;
    struct sockaddr * sa_tab[RTAX_MAX];
    int i;
    int r = -1;
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
        return -1;
    }
    if(l>0) {
        buf = malloc(l);
        if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
            return -1;
        }
        for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
            rt = (struct rt_msghdr *)p;
            sa = (struct sockaddr *)(rt + 1);
            for(i=0; i<RTAX_MAX; i++) {
                if(rt->rtm_addrs & (1 << i)) {
                    sa_tab[i] = sa;
                    sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
                } else {
                    sa_tab[i] = NULL;
                }
            }

            if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
               && sa_tab[RTAX_DST]->sa_family == AF_INET
               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {


                if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
                        char ifName[128];
                        if_indextoname(rt->rtm_index,ifName);
                        if(strcmp(TypeEN,ifName)==0){
                            *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
                                r = 0;                        
                        }
                }
            }
        }
        free(buf);
    }
    return r;
}
#endif

通过以下代码片段,本示例将在模拟器和设备上运行良好。

#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
    #include <net/route.h>
    #define TypeEN    "en1"
#else
    #include "route.h"
    #define TypeEN    "en0"
#endif

在你的Objective C项目中使用这段代码

#import "getgateway.h"
#import <arpa/inet.h>

- (NSString *)getGatewayIP {
    NSString *ipString = nil;
    struct in_addr gatewayaddr;
    int r = getdefaultgateway(&(gatewayaddr.s_addr));
    if(r >= 0) {
        ipString = [NSString stringWithFormat: @"%s",inet_ntoa(gatewayaddr)];
        NSLog(@"default gateway : %@", ipString );
    } else {
        NSLog(@"getdefaultgateway() failed");
    }

    return ipString;

}

我该如何更新代码以适用于IPv6网络? - Jongers
能否获取网络中所有WiFi网关的地址? - Boosa Ramesh
你让我开心极了,老兄...它像魔法一样运行得很好 :D... - Kalpesh Panchasara
Alex0072005,你愿意将这段代码上传到Github Gist并指定MIT许可证吗?2015年的Stack Overflow代码是以CC BY-SA 3.0发布的,不能轻易地用于MIT许可证项目。 - hemelamed
澄清一下,不需要MIT许可证,只需要更宽松的许可证。2015年的Stack Overflow代码以CC BY-SA 3.0的形式发布,未经重新分发,不能进行修改。这使得将其包含在具有不同许可证的开源软件中变得有些棘手。 - hemelamed
显示剩余2条评论

12
以下代码对我有效,但需要一份route.h的副本。
我的理解是,这段代码查询并检索系统路由表。它使用路由表条目来确定默认路由,也就是网关IP。
/* $Id: getgateway.c,v 1.6 2007/12/13 14:46:06 nanard Exp $ */
/* libnatpmp
 * Copyright (c) 2007, Thomas BERNARD <miniupnp@free.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include "getgateway.h"
#include "route.h"
#include <net/if.h>
#include <string.h>

#define CTL_NET         4               /* network, see socket.h */


#if defined(BSD) || defined(__APPLE__)

#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))

int getdefaultgateway(in_addr_t * addr)
{
    int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
        NET_RT_FLAGS, RTF_GATEWAY};
    size_t l;
    char * buf, * p;
    struct rt_msghdr * rt;
    struct sockaddr * sa;
    struct sockaddr * sa_tab[RTAX_MAX];
    int i;
    int r = -1;
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
        return -1;
    }
    if(l>0) {
        buf = malloc(l);
        if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
            return -1;
        }
        for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
            rt = (struct rt_msghdr *)p;
            sa = (struct sockaddr *)(rt + 1);
            for(i=0; i<RTAX_MAX; i++) {
                if(rt->rtm_addrs & (1 << i)) {
                    sa_tab[i] = sa;
                    sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
                } else {
                    sa_tab[i] = NULL;
                }
            }

            if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
               && sa_tab[RTAX_DST]->sa_family == AF_INET
               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {


                if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
                        char ifName[128];
                        if_indextoname(rt->rtm_index,ifName);

                        if(strcmp("en0",ifName)==0){

                                *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
                                r = 0;                        
                        }
                }
            }
        }
        free(buf);
    }
    return r;
}
#endif

2
对于任何在模拟器上尝试此操作的人,请注意:"en1"可能是活动网络连接,而不是"en0"。 - newenglander
2
你可以从这里获取route.h:http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/route.h。然后像这样获取网关:`struct in_addr gatewayaddr; int r = getdefaultgateway(&(gatewayaddr.s_addr)); if(r>=0){NSString * ipString = [NSString stringWithFormat: @"%s",inet_ntoa(gatewayaddr)];NSLog(@"默认网关 : %@", ipString );} else {NSLog(@"getdefaultgateway() 失败");}` - ddiego
嗨,使用3G时它无法工作,你能帮忙吗? - souvickcse
我遇到了这个错误:Undefined symbols for architecture arm64 "getdefaultgateway(unsigned int*)",你能帮我吗? - Jongers
为什么不在获取地址时中断? - Karsten
显示剩余3条评论

2

经过与苹果公司的核实,该软件开发工具包(SDK)并没有提供简便的方法来实现这一点。如果有的话,较为困难的方法是深入系统或使用跟踪路由(traceroute)。

我已提交了一个错误报告,也许他们会在未来添加这个功能。


-2

看一下Objective-C : 如何获取路由器地址?的答案。

也许只是有点关联,但请参考这篇博客文章中概述的技术:http://blog.zachwaugh.com/post/309927273/programmatically-retrieving-ip-address-of-iphone

它获取了Wi-Fi接口的IP地址,可能是找到另一个解决方案的另一个起点...

- (NSString *)getIPAddress
{
  NSString *address = @"error";
  struct ifaddrs *interfaces = NULL;
  struct ifaddrs *temp_addr = NULL;
  int success = 0;

  // retrieve the current interfaces - returns 0 on success
  success = getifaddrs(&interfaces);
  if (success == 0)
  {
    // Loop through linked list of interfaces
    temp_addr = interfaces;
    while(temp_addr != NULL)
    {
      if(temp_addr->ifa_addr->sa_family == AF_INET)
      {
        // Check if interface is en0 which is the wifi connection on the iPhone
        if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"])
        {
          // Get NSString from C String
          address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
        }
      }

      temp_addr = temp_addr->ifa_next;
    }
  }

  // Free memory
  freeifaddrs(interfaces);

  return address;
}

好的建议,应该检查返回的网关是否是WiFi接口上的网关。 - Jakob
1
以上代码返回的是设备的IP地址,而不是网关。 - Alena
1
...这是我在上一个段落中提到的。 - Paul Dixon
它确实返回设备IP地址... - Reimond Hill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接