之前我在做一个项目时遇到一个问题就是要获取wifi的网关,但是在网上搜了一下发现使用CNCopyCurrentNetWorkInfo这种方法只能获取到wifi的名称和mac地址,其他的都获取不到,而我所需要的是网关等信息,终于找了很久才找到解决方法,用C语言直接从底层获取这些信息,整个iOS的工程我已经放到github上了,大家可以到GitHub上下载,链接是 https://github.com/WrathLi/iOS_WIFI_Information
废话不多说,这里我们直接上代码。
首先,我新建了一个WifiManager的.h和.m文件,大家不要在意名字,我这人很懒,名字都是随便写的。
//返回广播地址,利用广播地址获取网关
- (NSString *) routerIp {
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 //ifa_addr
//ifa->ifa_dstaddr is the broadcast address, which explains the "255's"
// address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
//routerIP----192.168.1.255 广播地址
NSLog(@"broadcast address--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)]);
_wifiBroadcastAddress = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
//--192.168.1.106 本机地址
NSLog(@"local device ip--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)]);
_wifiIP = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
//--255.255.255.0 子网掩码地址
NSLog(@"netmask--%@",[NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)]);
_wifiNetMast = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)];
//--en0 端口地址
NSLog(@"interface--%@",[NSString stringWithUTF8String:temp_addr->ifa_name]);
_wifiInterface = [NSString stringWithUTF8String:temp_addr->ifa_name];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
上面这个方法是获取除网关之外的wifi信息的,网关的获取要在C文件下获取,这里返回广播地址,利用广播地址来获取网关。
char * getdefaultgateway(in_addr_t * addr)
{
#if 0
/* net.route.0.inet.dump.0.0 ? */
int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
NET_RT_DUMP, 0, 0/*tableid*/};
#endif
/* net.route.0.inet.flags.gateway */
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;
static char tmp[20];
if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
return tmp;
}
if(l>0) {
buf = malloc(l);
if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
return tmp;
}
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) {
unsigned char octet[4] = {0,0,0,0};
for (int i=0; i<4; i++){
octet[i] = ( ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr >> (i*8) ) & 0xFF;
}
if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
r = 0;
sprintf(tmp,"%d.%d.%d.%d",octet[0],octet[1],octet[2],octet[3]);
printf("gateway : %s\n",tmp);
printf("gateway address--%d.%d.%d.%d\n",octet[0],octet[1],octet[2],octet[3]);
}
}
}
free(buf);
}
return tmp;
}
getgateway这个方法返回了网关,不过是char * 类型的,如果你要把它转化成NSString类型,只要使用[[NSString alloc] initWithFormat:@"%s",gateway];这段代码就可以了。
好了,这是我第一次在CSDN上写博客,就写到这里吧。希望对有需要的人有帮助。