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. Codeforces Beta Round #37 C. Old Berland Language 暴力 dfs

    C. Old Berland Language 题目连接: http://www.codeforces.com/contest/37/problem/C Description Berland sci ...

  2. tyvj 1044 数字三角形 记忆化搜索

    数字三角形 Time Limit: 1 Sec  Memory Limit: 162 MB 题目连接 http://www.tyvj.cn/p/1044 Description 示出了一个数字三角形. ...

  3. wikioi 1068 乌龟棋

    四维dp表示分别用了多少张卡后可以获得的最大分数 #include <cstdio> #include <cmath> #include <cstring> #in ...

  4. Linux下Qt安装

    1.下载qt-everywhere-opensource-src4.7.2.tar.gz(http://download.qt.io/archive/qt/4.7),并解压在/opt目录下,文件名为q ...

  5. C++中使用REST操作

    REST现在是非常流行的一种接口了,但对于C++这种古董语言来说,用起来并不很方便.无论是json操作还是http交互,用起来都比较麻烦. 如果你需要在c++中使用rest操作时,不妨试一下微软的cp ...

  6. RAD Studio 2010~XE8 官方 ISO 下载地址 (2015-03-28更新)

    http://bbs.csdn.net/topics/390816856 RAD Studio XE8 目前最新版 v22.0.19027.8951 官方 ISO 文件下载(6.72GB):http: ...

  7. /dev/rdsk 与 /dev/dsk区别

    /dev/rdsk/c0t0d0s0 裸设备 /dev/dsk/c0t0d0s0 块设备 它们链接的是同一块物理设备,具体区别是在访问方式上. 裸设备是假设硬盘上没有文件系统时的访问方式. 裸设备是按 ...

  8. 淘宝海量数据库之八-攻克随机IO难关 -----阿里正祥的博客

    http://blog.sina.com.cn/s/blog_3fc85e260100qwv8.html

  9. jquery获取单选button选中的值

    在页面上单选button的代码: <s:iterator value="@com.hljw.cmeav.util.CmeavGlobal@isComMap"> < ...

  10. dubbo白名单通过filter,spring web通过拦截器或者filter即可

    在开发中,有时候需要限制访问的权限,白名单就是一种方法.对于Java Web应用,Spring的拦截器可以拦截Web接口的调用:而对于dubbo接口,Spring的拦截器就不管用了. dubbo提供了 ...