0
点赞
收藏
分享

微信扫一扫

Linux【网络库】| 【01 <ifaddr.h>】以及网络常用结构体

文章目录

一、简介

二、网络常用结构体

1、ifaddrs

struct ifaddrs {
	struct ifaddrs  *ifa_next;    // 指向列表中下一个结构的指针。该字段在列表的最后一个结构中为 NULL
	
	char            *ifa_name;   // 接口名称
	
	unsigned int     ifa_flags;   // 提供有关接口的一些信息的标志
	
	struct sockaddr *ifa_addr;   // 接口地址
	
	struct sockaddr *ifa_netmask; // 接口的网络掩码
	
	union {
	    struct sockaddr *ifu_broadaddr;		// 接口广播地址
	    struct sockaddr *ifu_dstaddr;	    // 点对点目的地址                 
	} ifa_ifu;
	
	#define              ifa_broadaddr ifa_ifu.ifu_broadaddr
	#define              ifa_dstaddr   ifa_ifu.ifu_dstaddr

	void            *ifa_data;    	// 特定地址族数据的缓冲区
};

2、sockaddr

struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

3、sockaddr_in

struct sockaddr_in {
    short            sin_family;   // 网络协议
    unsigned short   sin_port;     // 端口
    struct in_addr   sin_addr;     // ip
    char             sin_zero[8];  
};

struct in_addr {
    unsigned long s_addr;  // 使用 inet_aton() 加载
};

4、sockaddr_in6

struct sockaddr_in6 {
               sa_family_t     sin6_family;   /* 网络协议 */
               in_port_t       sin6_port;     /* 端口 */
               uint32_t        sin6_flowinfo; /* IPv6 流信息 */
               struct in6_addr sin6_addr;     /* ip */
               uint32_t        sin6_scope_id; 
           };

           struct in6_addr {
               unsigned char   s6_addr[16];   /* IPv6 address */
           };

三、常用函数

1、getifaddrs

#include <sys/types.h>
#include <ifaddrs.h>

int getifaddrs(struct ifaddrs **ifap);
/**
* func:函数存储对ifaddrs结构的链表的引用;
* return:成功返回0,失败返回-1;
*/
【注意】: 返回的数据是动态分配的,需要释放;

2、freeifaddrs

#include <sys/types.h>
#include <ifaddrs.h>

void freeifaddrs(struct ifaddrs *ifa);
/**
* func:释放对ifaddrs结构的链表的引用;
*/

3、getnameinfo

#include <sys/socket.h>
#include <netdb.h>

int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                       char *host, size_t hostlen,
                       char *serv, size_t servlen, int flags);
/**
* func:将套接字地址转换为相应的主机和服务并返回;
* @param sa:套接字地址结构,保存输入的IP地址和端口号;
* @param salen:sa的长度;
* @param host:调用者分配缓冲区;
* @param hostlen:host长度;
* @param serv:调用者分配缓冲区;
* @param servlen:serv长度
* @param flags:
		NI_NAMEREQD:若无法确定主机名,则返回一个错误;
		NI_DGRAM:基于数据报(UDP)而不是基于流(TCP)的;
		NI_NOFQDN:只返回本地主机的完全限定域名的主机名部分;
		NI_NUMERICHOST:返回主机名的数字形式;
		NI_NUMERICSERV:返回服务地址的数字形式;
		
* return:成功返回0,【节点和服务名称将使用以空字符结尾的字符串填充】;
	失败设置errno:
		EAI_AGAIN:			无法解析该名称, 稍后再试;
		EAI_BADFLAGS:		flags参数的值无效;
		EAI_FAIL:			不可恢复的错误;
		EAI_FAMILY:		无法识别地址族,或指定地址族的地址长度无效
      	EAI_MEMORY:		溢出;
 	 	EAI_NONAME:		名称不能解析所提供的参数
		EAI_OVERFLOW:		溢出;
        EAI_SYSTEM:		系统错误;
*/
【注意】:调用者可以通过提供一个NULL host(或serv)参数或一个零hostlen(或servlen)参数来指定不需要主机名(或不需要服
务名)。 但是,必须请求至少一个主机名或服务名。

四、案例

/*----------------------------------------------------------------------
	> File Name: test.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Tue 22 Mar 2022 02:53:07 PM CST
----------------------------------------------------------------------*/
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr, *ifa;
    int family, s;
    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }

    /* 遍历链表,维护头指针,以便稍后可以释放链表  */
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL)
            continue;

        family = ifa->ifa_addr->sa_family;


        /* 显示接口名称和族 */
        printf("%s  address family: %d%s\n",
                ifa->ifa_name, family,
                (family == AF_PACKET) ? " (AF_PACKET)" :
                (family == AF_INET) ?   " (AF_INET)" :
                (family == AF_INET6) ?  " (AF_INET6)" : "");

        /* For an AF_INET* interface address, display the address */

        if (family == AF_INET || family == AF_INET6) {
            s = getnameinfo(ifa->ifa_addr,
                    (family == AF_INET) ? sizeof(struct sockaddr_in) :
                    sizeof(struct sockaddr_in6),
                    host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
            if (s != 0) {
                printf("getnameinfo() failed: %s\n", gai_strerror(s));
                exit(EXIT_FAILURE);
            }
            printf("\taddress: <%s>\n", host);
        }
    }
    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}
举报

相关推荐

0 条评论