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实现微信公众平台开发 全套视频资源下载
- Happy Programming Contest(ZOJ3703)(01背包+路径储存)
- 传智播客C++第五期培训视频教程免费下载
- bzoj 1492 [NOI2007]货币兑换Cash(斜率dp+cdq分治)
- javadoc入门
- wcf事务(随记)
- Python多进程应用
- python 列表解析
- 分布式进阶(四)Ubuntu 14.04下安装Tomcat 6
- Netty1:初识Netty
- Linux framebuffer测试程序
- PHP 【三】
- 【app】adb连接问题整理
- centos7安装Lnmp(Linux+Nginx+MySql+Php+phpMyAdmin+Apache)
- Ibatis.Net 执行存储过程学习(八)
- SearchBySql
- golang学习笔记 ---数组与切片
- 48位MAC转化为唯一的128位IPV6地址
- [原创]C/C++语言中,如何在main.c或main.cpp中调用另一个.c文件
- 命名实体识别(NER)
热门文章
- Codeforces Round #288 (Div. 2) E. Arthur and Brackets 贪心
- mysql慢查询配置
- JavaMail_测试编写
- ServletActionContext.getRequest().getSession() 和 ActionContext.getContext().getSession()
- oracle备份恢复学习
- 3D数学读书笔记——四元数
- linux内核源码中常见宏定义
- OLEDB Excel 与C# 的数据流通方法
- 配置quartz数据源的三种方式
- putty如何退出全屏模式