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 Round #257 (Div. 2) C. Jzzhu and Chocolate

    C. Jzzhu and Chocolate time limit per test 1 second memory limit per test 256 megabytes input standa ...

  2. servlet注入service业务bean

    项目中用到spring容器来管理业务bean,在servlet中就收到前台传递来的请求参数后,调用业务bean,老是出错 部门代码如下 <span style="font-size:1 ...

  3. 转:Windows中的命令行提示符里的Start命令执行路径包含空格时的问题

    转自:http://www.x2009.net/articles/windows-command-line-prompt-start-path-space.html 当使用Windows 中的命令行提 ...

  4. Get started with IDA and disassembly SH7058

    http://www.romraider.com/forum/viewtopic.php?f=25&t=6303 All of the 16-bit guidance in the follo ...

  5. SyncThingWin -- Run syncthing as a windows service

    SyncThingWin Auto restart and minor bug fixes bloones released this on 23 Dec 2014 There is now an a ...

  6. C#遍历系统所安装的打印机,使用WMI方式获取打印机的所有属性

    有网友发消息来询问,C#如何遍历系统已经安装的所有打印机,并获得每个打印机的相关信息,如:端口,名称等等 C#里面,虽然在 System.Drawing.Printing 这个namespace下,提 ...

  7. CMMI之功能点估算法---内部逻辑文件和外部接口文件

    功能点分析的步骤 在本文中将以国际标准IFPUG(International Function Point Users Group)组织提供的功能点估算法V4.1.1为基础与大家进行讲解.如下图所示, ...

  8. 算法:合并排序(Merge Sort)

    算法定义 合并排序是一种递归算法,思路如下: 如果源数组长度为 1,立即返回. 将源数组平分为两个新数组:Left 和 Right. 对 Left 执行递归排序. 对 Right 执行递归排序. 将排 ...

  9. 《Windows核心编程》第2章——字符和字符处理

    ANSI和UNICODE 计算char和wchar_t的长度都一样,都是5,但是二者在内存中的布局实际上是不同的:

  10. 采用Operator-sdk轻松将helm chart转为Operator

    去年就接触Operator,从Oracle发布的WebLogic Operator到mySQL Operator,构建的源码一大堆,但感觉一直缺少合适的开发框架能够避免复杂性快速生成, 随着技术的日益 ...