在linux下,我们知道可以通过ifconfig获取mac地址和ip地址等相关信息,如何在程序中获取这些网络信息,我们就需要使用到Linux系统所提供的一个函数ioctl(),iotec函数是对设备的i/o通道进行管理的函数。ioctl这个函数,可以用来对特殊文件的基础设备参数进行操作,它们可以完成与打开文件描述符相关联的控制功能。在程序启动时获得主机上所有接口的信息: 接口的地址、接口是否支持广播、是否支持多播等等。成功返回0,出错则返回-1。
其中,struct ifreq 就是用来存储返回的接口相关信息的结构体,一般情况下,电脑有多个硬件接口,因此Linux系统使用指针来存储返回的结构体数组。struct ifconf 变量是用来存储ioctl()函数返回结果的。因为我们是要获取mac地址的相关信息。
struct ifreq
ifreq用来保存某个接口信息
struct ifreq
{
char ifr_name[IFNAMSIZ];
Union{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_metric;
caddr_t ifru_data;
}ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_broadaddr ifr_ifru.ifru_broadadd
#define ifr_hwaddr ifr_ifru_hwaddr
if(ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)
{
perror("ioctl get addr");
c_return(sockfd, -1);
}
psin = (struct sockaddr_in*)&ifr.ifr_addr;
strcpy((char*)pei->ip, (char*)inet_ntoa(psin->sin_addr));
上述代码获取IP地址
struct ifconf
获取本地IP
本文里只是单独对获取网络接口信息部分讲解。
先列出一些本文里ioctl的相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
request参数 | 相关说明 | 指向数据类型 |
SIOCGIFCONF | 获取所有接口信息 | struct ifconf |
SIOCGIFADDR | 获取接口地址 | struct ifreq |
SIOCGIFFLAGS | 获取接口状态 | struct ifreq |
SIOCGIFBRDADDR | 获取广播地址 | struct ifreq |
SIOCGIFNETMASK | 获取子网掩码 | struct ifreq |
ioctl(sock, SIOCGIFHWADDR, &ifr) 获取网卡mac地址
ioctl(sock, SIOCGIFINDEX, &ifr)获取网卡接口地址(IP地址)ioctl(sock, SIOCGIFHWADDR, &ifr) 获取子网掩码
为什么进行绑定时只需要接口地址而不需要mac地址呢?
推测:是不是mac地址bind也可以,接口地址也可以,两者取一即可,只不过接口地址比较方便。
网卡接口索引唯一标记本机上的一块网卡,所以依据此索引,可以定位到本机上指定的一块网卡上。有多个网卡的时候,每个网卡都有一个索引值,是会随着网卡正在被使用的个数变化。
接下来,就开始利用ioctl以及其参数来获取网络接口的信息了。
struct ethif
{
char ifname[_ETH_NAME_LEN];
char ip[_IP_LEN];
unsigned char mac[_MAC_LEN];
char netmask[_IP_LEN];
int ifindex;
};