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;
};
ifconf和ifreq的更多相关文章
- 两个结构体ifconf和ifreq
用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人来说都是比较陌生的,这里给大家一种比较简单的理解方法,当然只一种帮助理解的方法,在描述中可能会有一些地方与真实定 ...
- 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf
转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq 结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...
- ifreq、ifconf
网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示: 接口 SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFBRDADDR SI ...
- linux网络接口,struct ifreq struct ifconf结构
网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示: 接口 SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFBRDADDR SI ...
- struct ifreq学习和实例
一.struct ifreq结构体 这个结构定义在/usr/include/net/if.h,用来配置和获取ip地址,掩码,MTU等接口信息的. /* Interface request struct ...
- (十)Linux 网络编程之ioctl函数
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- linux内核数据结构学习总结
目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...
- Linux网络编程实例解析
**************************************************************************************************** ...
- linux编程获取本机网络相关参数
getifaddrs()和struct ifaddrs的使用,获取本机IP 博客分类: Linux C编程 ifaddrs结构体定义如下: struct ifaddrs { struct ifad ...
随机推荐
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure 分治暴力
D. Vanya and Treasure 题目连接: http://www.codeforces.com/contest/677/problem/D Description Vanya is in ...
- Codeforces Round #222 (Div. 1) B. Preparing for the Contest 二分+线段树
B. Preparing for the Contest 题目连接: http://codeforces.com/contest/377/problem/B Description Soon ther ...
- centos7 docker安装和使用_入门教程
说明:本文也是参考互联网上的文章写的,感谢相关作者的贡献. 操作系统 64位CentOS Linux release 7.2.1511 (Core) 配置好IP:192.168.1.160 修改yum ...
- c# 对字符串反序列成匿名对象
/// <summary> /// 需求单列表 /// </summary> /// <param name="model"></para ...
- systemtap 探针定制
http://blog.163.com/digoal@126/blog/static/163877040201391123645546/
- Javascript 面向对象编程(一):封装(转载)
Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果 ...
- Lucene新版本号对ConjunctionScorer的优化
Lucene 4.0版本号的DocIdSetIterator中没有cost方法,而4.7.0则有这种方法,表示遍历整个DocIdSet的代价,对于DocsEnum就是其长度了,对于Scorer就能够是 ...
- 21扩展IEnumerable<T>泛型接口自定义LINQ的扩展方法
LINQ方法实际上是对IEnumerable<TSource>的扩展,如图: 本篇自定义一个MyWhere方法,达到与Where相同的效果. 使用LINQ自带的Where方法 ...
- go语言 defer 高级
go语言defer语句的用法 defer的语法 defer后面必须是函数调用语句,不能是其他语句,否则编译器会出错. package main import "log" func ...
- oracle转义符
要使用_,则需要做如下转义 select column_name from user_tab_columns where table_name = 'SYS_TERMINAL_MAPPING' AND ...