• ifconf和ifreq


    http://blog.csdn.net/jasenwan88/article/details/7763689

    用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人来说都是比较陌生的,这里给一种比较简单的理解方法, 仅供参考.

    首先先认识一下ifconf和ifreq:

    //ifconf通常是用来保存所有接口信息的 //ifreq用来保存某个接口的信息
    //if.h
    struct ifreq {
    char ifr_name[IFNAMSIZ];
    union {
    struct sockaddr ifru_addr;
    struct sockaddr ifru_dstaddr;
    struct sockaddr ifru_broadaddr;
    short ifru_flags;
    int ifru_metric;
    caddr_t ifru_data;
    } ifr_ifru;
    };
    #define ifr_addr ifr_ifru.ifru_addr
    #define ifr_dstaddr ifr_ifru.ifru_dstaddr
    #define ifr_broadaddr ifr_ifru.ifru_broadaddr

     

    上边这两个结构看起来比较复杂,我们现在把它们简单化一些:比如说现在我们向实现获得本地IP的功能。

    我们的做法是:1. 先通过ioctl获得本地所有接口的信息,并保存在ifconf中2. 再从ifconf中取出每一个ifreq中表示ip地址的信息

    具体使用时我们可以认为ifconf就有两个成员:ifc_len 和 ifc_buf,如图一所示:    

    ifc_len:表示用来存放所有接口信息的缓冲区长度ifc_buf:表示存放接口信息的缓冲区

    所以我们需要在程序开始时对ifconf的ifc_len和ifc_buf进行初始化接下来使用ioctl获取所有接口信息,完成后ifc_len内存放实际获得的接口信息总长度,并且信息被存放在ifc_buf中。如下图示:(假设读到两个接口信息)

    接下来我们只需要从一个一个的接口信息获取ip地址信息即可。

    下面有一个简单的参考:

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    int main(void)
    {
    int i=0;
    int sockfd;
    struct ifconf ifconf;
    unsigned char buf[512];
    struct ifreq *ifreq; //初始化ifconf
    ifconf.ifc_len = 512;
    ifconf.ifc_buf = buf;
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
    {
    perror("socket");
    exit(1);
    }
    ioctl(sockfd, SIOCGIFCONF, &ifconf); //获取所有接口信息
    //逐个获取IP地址
    ifreq = (struct ifreq*)buf;
    for(i=(ifconf.ifc_len/sizeof(struct ifreq)); i>0; i--)
    {
    //if(ifreq->ifr_flags == AF_INET){
    //for ipv4
    printf("name = [%s]n", ifreq->ifr_name);
    printf("local addr = [%s]n",inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));
    ifreq++;
    //}
    }
    return 0;
    }


    另一种方式(可以获取所有的接口信息,前例子加入有多个网卡的话,信息有可能无法完全获取):
        unsigned int buffer_size = 4096; // initial guess
        unsigned int last_size = 0;
        struct ifconf config;
        unsigned char* buffer;
        for (;buffesr_size < 65536;) {
            buffer = new unsigned char[buffer_size];
            config.ifc_len = buffer_size;
            config.ifc_buf = (char*)buffer;
            if (ioctl(net, SIOCGIFCONF, &config) < 0) {
                if (errno != EINVAL || last_size != 0) {
                    return NPT_ERROR_BASE_UNIX-errno;
                }
            } else {
                if ((unsigned int)config.ifc_len == last_size) {
                    // same size, we can use the buffer
                    break;
                }
                // different size, we need to reallocate
                last_size = config.ifc_len;
            }
            
            // supply 4096 more bytes more next time around
            buffer_size += 4096;
            delete[] buffer;
        }

    struct ifreq

    这个结构定义在include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的struct ifreq
      {
    # define IFHWADDRLEN    6
    # define IFNAMSIZ   IF_NAMESIZE
        union
          {   
        char ifrn_name[IFNAMSIZ];   /* Interface name, e.g. "en0".  */
          } ifr_ifrn;

        union
          {   
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        struct sockaddr ifru_netmask;
        struct sockaddr ifru_hwaddr;
        short int ifru_flags;
        int ifru_ivalue;
        int ifru_mtu;
        struct ifmap ifru_map;
        char ifru_slave[IFNAMSIZ];  /* Just fits the size */
        char ifru_newname[IFNAMSIZ];
        __caddr_t ifru_data;
          } ifr_ifru;
      }; 

    struct  ifconf

    通常是用来保存所有接口信息的


    struct ifconf
      {
        int ifc_len;            /* Size of buffer.  */
        union
          {
        __caddr_t ifcu_buf;
        struct ifreq *ifcu_req;
          } ifc_ifcu;
      };

    
    
  • 相关阅读:
    PHP 数组函数分类整理
    mysql 数据库中 int(3) 和 int(11) 有区别么???
    理解PHP的运行机制
    类与对象
    PHP函数补完:call_user_func()
    linux 软件安装目录详解
    Linux下安装Redis
    Redis简介,应用场景,优势
    idea自动抽取变量快捷键设置
    全局捕获异常(适用于SpringMvc,SpringBoot项目)
  • 原文地址:https://www.cnblogs.com/jingzhishen/p/3449429.html
Copyright © 2020-2023  润新知