获取本地的局域网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网络编程》中介绍的非常详细。