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;
  };


ifconf和ifreq的更多相关文章

  1. 两个结构体ifconf和ifreq

    用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人来说都是比较陌生的,这里给大家一种比较简单的理解方法,当然只一种帮助理解的方法,在描述中可能会有一些地方与真实定 ...

  2. 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq  结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...

  3. ifreq、ifconf

    网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示: 接口 SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFBRDADDR SI ...

  4. linux网络接口,struct ifreq struct ifconf结构

    网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示: 接口 SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFBRDADDR SI ...

  5. struct ifreq学习和实例

    一.struct ifreq结构体 这个结构定义在/usr/include/net/if.h,用来配置和获取ip地址,掩码,MTU等接口信息的. /* Interface request struct ...

  6. (十)Linux 网络编程之ioctl函数

    1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...

  7. linux内核数据结构学习总结

    目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...

  8. Linux网络编程实例解析

    **************************************************************************************************** ...

  9. linux编程获取本机网络相关参数

    getifaddrs()和struct ifaddrs的使用,获取本机IP 博客分类: Linux C编程   ifaddrs结构体定义如下: struct ifaddrs { struct ifad ...

随机推荐

  1. 【对比分析五】CSS阻塞和JS阻塞

    js 的阻塞特性: 所有浏览器在下载 JS 的时候,会阻止一切其他活动,比如其他资源的下载,内容的呈现等等.直到 JS 下载.解析.执行完毕后才开始继续并行下载其他资源并呈现内容.为了提高用户体验,新 ...

  2. angularJS简介及其特点—— 五大特性,加快 Web 应用开发

    AngularJS 是谷歌的一个 JavaScript 框架,旨在简化前端应用程序的开发. 一. 关于和jquery的比较 首先angular是一个mvc框架,它与jquery不同之处在于,前者致力于 ...

  3. Git_集中式vs分布式

    创建版本库 时光机穿梭 版本回退 工作区和暂存区 管理修改 撤销修改 删除文件 远程仓库 添加远程库 从远程库克隆 分支管理 创建与合并分支 解决冲突 分支管理策略 Bug分支 Feature分支 多 ...

  4. Android 5.0 源代码结构

    本节书摘来自异步社区<深入理解Android 5 源代码>一书中的第2章,第2.2节分析Android源代码结构,作者 李骏. 网址:https://yq.aliyun.com/artic ...

  5. JSON在PHP中的基本应用

    从5.2版本开始,PHP原生提供json_encode()和json_decode()函数,前者用于编码,后者用于解码. 一.json_encode() 该函数主要用来将数组和对象,转换为json格式 ...

  6. CentOS的update-grub2命令

    这个和Ubuntu还是有些区别,在CentOS修改成如下: grub2-mkconfig -o /boot/grub2/grub.cfg

  7. FastBoot BootLoader Recovery 模式解释

    理论上,所有的Android设备都存在着Fastboot/Bootloader模式,不过,由于Android操作系统的开源特性,各厂商的对 自家的相关Android设备都有着各自不同的Fastboot ...

  8. ibatis实战之中的一个对多关联

    在实际开发中,我们经常遇到关联数据的情况,如User对象拥有若干Book对象 每一个Book对象描写叙述了归属于一个User信息,这样的情况下,我们应该怎样处理? 通过单独的Statement操作固然 ...

  9. [Asp.net MVC]页面伪静态实现

    摘要 从页面Url及页面名称上看,你会发现静态页面和伪静态是一样的.伪静态的页面后缀可能是html,htm,cshtml等,只是改变了url的表现形式,实际上还是动态的页面.在SEO方面,伪静态和静态 ...

  10. .NET泛型03,泛型类型的转换,协变和逆变

    协变(Convariant)和逆变(Contravariant)的出现,使数组.委托.泛型类型的隐式转换变得可能. 子类转换成基类,称之为协变:基类转换成子类,称之为逆变..NET4.0以来,支持了泛 ...