获取本地的局域网IP地址,个人认为最好的还是这个神器---ioctl,这个接口的功能真是非常强大,非常值得研究和学习。即使本地的主机名是localhost,使用ioctl也可以轻松地获取局域网中的IP地址,而且不需要在/etc/hosts中绑定局域网IP。使用ioctl来获取本地局域网IP地址,需要首先创建一个套接字和一个struct ifreq结构(值-结果参数),下面首先介绍struct ifreq结构。
一、ioctl中需要用到的结构----struct ifreq
这个结构的定义是在/usr/include/linux/if.h中,但是在使用时不要直接包含这个头文件,而是使用/usr/include/net/if.h这个头文件,其定义如下所示:
struct ifreq
{
#define IFHWADDRLEN 6
union
{
char ifrn_name[IFNAMSIZ]; /* if 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 ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
void * ifru_data;
struct if_settings ifru_settings;
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_map ifr_ifru.ifru_map /* device map */
#define ifr_slave ifr_ifru.ifru_slave /* slave device */
#define ifr_data ifr_ifru.ifru_data /* for use by interface */
#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
#define ifr_newname ifr_ifru.ifru_newname /* New name */
#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/
通过这个结构的定义就可以知道,通过ioctl可以获取非常多有用的信息,包括子网掩码,物理地址,MTU等非常有价值、有意义的信息。在访问struct ifreq结构的成员时,最好使用下面定义的一些宏,这样比较方便,而且代码也比较规范,不要直接像普通结构体那样访问它的成员。在调用ioctl时,需要制定的成员是ifr_name成员,需要指定要获取那个网络接口的IP地址,如果要获取eth0接口的地址,就使用字符串"eth0"来初始化。
二、 代码示例
具体的代码如下:
#include <stdio.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <string.h>
int main(void)
{
int fd;
char buf[100];
struct ifreq ifr;
struct sockaddr_in *sa = NULL;
fd = socket(AF_INET, SOCK_STREAM, 0);
strcpy(ifr.ifr_name, "eth0");
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
perror("ioctl");
}
sa = (struct sockaddr_in *)(&ifr.ifr_addr);
printf("ip: %s\n", inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof (buf)));
return 0;
}
Linux下获取本地IP地址的介绍只介绍getaddrinfo接口和ioctl接口两种方式,其他的比如gethostbyname和gethostent就不介绍了,《Unix网络编程》中介绍的非常详细。
转自:javascript:void(0)
获取本地的局域网IP地址,个人认为最好的还是这个神器---ioctl,这个接口的功能真是非常强大,非常值得研究和学习。即使本地的主机名是localhost,使用ioctl也可以轻松地获取局域网中的IP地址,而且不需要在/etc/hosts中绑定局域网IP。使用ioctl来获取本地局域网IP地址,需要首先创建一个套接字和一个struct ifreq结构(值-结果参数),下面首先介绍struct ifreq结构。
一、ioctl中需要用到的结构----struct ifreq
这个结构的定义是在/usr/include/linux/if.h中,但是在使用时不要直接包含这个头文件,而是使用/usr/include/net/if.h这个头文件,其定义如下所示:
struct ifreq
{
#define IFHWADDRLEN 6
union
{
char ifrn_name[IFNAMSIZ]; /* if 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 ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
void * ifru_data;
struct if_settings ifru_settings;
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_map ifr_ifru.ifru_map /* device map */
#define ifr_slave ifr_ifru.ifru_slave /* slave device */
#define ifr_data ifr_ifru.ifru_data /* for use by interface */
#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
#define ifr_newname ifr_ifru.ifru_newname /* New name */
#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/
通过这个结构的定义就可以知道,通过ioctl可以获取非常多有用的信息,包括子网掩码,物理地址,MTU等非常有价值、有意义的信息。在访问struct ifreq结构的成员时,最好使用下面定义的一些宏,这样比较方便,而且代码也比较规范,不要直接像普通结构体那样访问它的成员。在调用ioctl时,需要制定的成员是ifr_name成员,需要指定要获取那个网络接口的IP地址,如果要获取eth0接口的地址,就使用字符串"eth0"来初始化。
二、 代码示例
具体的代码如下:
#include <stdio.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <string.h>
int main(void)
{
int fd;
char buf[100];
struct ifreq ifr;
struct sockaddr_in *sa = NULL;
fd = socket(AF_INET, SOCK_STREAM, 0);
strcpy(ifr.ifr_name, "eth0");
if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
perror("ioctl");
}
sa = (struct sockaddr_in *)(&ifr.ifr_addr);
printf("ip: %s\n", inet_ntop(AF_INET, &sa->sin_addr, buf, sizeof (buf)));
return 0;
}
Linux下获取本地IP地址的介绍只介绍getaddrinfo接口和ioctl接口两种方式,其他的比如gethostbyname和gethostent就不介绍了,《Unix网络编程》中介绍的非常详细。