ios获取网络接口信息的函数

最近在做Unity局域网对战游戏,需要获取当前可用的IP地址。要使用热点作为外网接入点,使用mono c#的api获取的ip信息是错误的,因此用native的方式来实现。
以下是一个测试版本的代码:

//
//  NetInfoHelper.m
//  Unity-iPhone
//
//  Created by yupeng on 8/18/16.
//
//

#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <errno.h>
#include <net/if_dl.h>
#include <net/ethernet.h>

#define MAX_IP_SIZE 16
#define MAX_BUFFER_SIZE 4096
#define TARGET_HAED_ADDR "02:00:00:00:00:00"
#define max(a,b) ((a)>(b)?(a):(b))

char* ip_int_names[MAX_IP_SIZE];
char* ip_addr_strs[MAX_IP_SIZE];
char* ip_hardwares[MAX_IP_SIZE];
char* ip_masks[MAX_IP_SIZE];

static uint8_t max_ip_count = 0;
void GetCurNetInfo()
{
    uint8_t idx = 0;
    for (; idx < MAX_IP_SIZE; idx++)
    {
        ip_int_names[idx] = ip_addr_strs[idx] = ip_hardwares[idx] = ip_masks[idx] = NULL;
    }
    idx = 0;

    struct ifaddrs *interfaces;
    if(!getifaddrs(&interfaces))
    {
        struct ifaddrs *interface;
        for(interface=interfaces; interface; interface=interface->ifa_next)
        {
            if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ )//ignore ipv6
            {
                continue;
            }
            const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
            char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
            if(addr && (addr->sin_family==AF_INET /*|| addr->sin_family==AF_INET6*/))
            {
                char *name = interface->ifa_name;
                char *netmask = inet_ntoa(((struct sockaddr_in*)interface->ifa_netmask)->sin_addr);

                if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN))
                {
                    printf("netmask = %s name = %s ip = %s \n" , netmask, name, addrBuf);
                    ip_int_names[idx] = (char*)malloc(strlen(name) + 1);
                    ip_addr_strs[idx] = (char*)malloc(strlen(addrBuf) + 1);
                    ip_masks[idx] = (char*)malloc(strlen(netmask) + 1);
                    if(NULL == ip_int_names[idx] || NULL == ip_addr_strs[idx] || NULL == ip_masks[idx])
                    {
                        return;
                    }
                    strcpy(ip_int_names[idx], name);
                    strcpy(ip_addr_strs[idx], addrBuf);
                    strcpy(ip_masks[idx], netmask);
                    idx++;
                }
            }
        }
        max_ip_count = idx;
        freeifaddrs(interfaces);
    } 
}

void GetHWAddresses()
{
    struct ifconf ifc;
    struct ifreq *ifr;
    int sockfd;
    char buffer[MAX_BUFFER_SIZE], *cp, *cplim;
    char temp[80];

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket failed");
        return;
    }

    ifc.ifc_len = MAX_BUFFER_SIZE;
    ifc.ifc_buf = buffer;

    if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
    {
        perror("ioctl error");
        close(sockfd);
        return;
    }

    ifr = ifc.ifc_req;

    cplim = buffer + ifc.ifc_len;

    for (cp=buffer; cp < cplim; )
    {
        ifr = (struct ifreq *)cp;
        if (ifr->ifr_addr.sa_family == AF_LINK)
        {
            struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
            int a,b,c,d,e,f;
            int i;

            strcpy(temp, (char *)ether_ntoa((const struct ether_addr *)LLADDR(sdl)));
            sscanf(temp, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);
            sprintf(temp, "%02X:%02X:%02X:%02X:%02X:%02X",a,b,c,d,e,f);

            for (i=0; i<max_ip_count; ++i)
            {
                if ((ip_int_names[i] != NULL) && (strcmp(ifr->ifr_name, ip_int_names[i]) == 0))
                {
                    if (ip_hardwares[i] == NULL)
                    {
                        ip_hardwares[i] = (char *)malloc(strlen(temp)+1);
                        strcpy(ip_hardwares[i], temp);
                        printf("hdaddr = %s ipaddr = %s name = %s \n", ip_hardwares[i], ip_addr_strs[i], ip_int_names[i]);
                        break;
                    }
                }
            }
        }
        cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
    }
    close(sockfd);
}

//计算当前可用的广播地址
//先用mask&ip得到ip地址
const char* calculate_broadcast_ip(const char* ip_addr, const char* mask_addr)
{
    printf("ipaddr = %s mask = %s \n", ip_addr, mask_addr);
    struct in_addr ip;
    struct in_addr mask;

    if(0 == inet_aton(ip_addr, &ip))
    {
        return NULL;
    }
    if(0 == inet_aton(mask_addr, &mask))
    {
        return NULL;
    }

    ip.s_addr = ip.s_addr & mask.s_addr;
    printf("net ip addr = %s \n", inet_ntoa(ip));
    mask.s_addr = (mask.s_addr ^ 0xFFFFFFFF);
    printf("mask ip ^ = %s", inet_ntoa(mask));
    ip.s_addr = ip.s_addr | mask.s_addr;
    printf("broadcast ip addr = %s \n", inet_ntoa(ip));
    return inet_ntoa(ip);
}

void GetTargetIpInfo()
{
    uint8_t idx = 0;
    for (; idx < max_ip_count; idx++)
    {
        if(0 == strcmp(ip_hardwares[idx], TARGET_HAED_ADDR))
        {
            calculate_broadcast_ip(ip_addr_strs[idx], ip_masks[idx]);
        }
    }
}

#ifdef __cplusplus
extern "C"{
#endif

    void PrintCurNetInfo()
    {
        GetCurNetInfo();
        GetHWAddresses();
        GetTargetIpInfo();
    }

#ifdef __cplusplus
}
#endif
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值