C语言获取Linux单网卡的多IP地址

简介: C语言获取Linux单网卡的多IP地址

环境配置

上一篇文章主要讲了AIX系统下的单网卡多IP的IP的配置以及C语言获取的方法。相比AIX,Linux下配置就方便得多。

首先找到我们需要配置的网卡名,比如p2p2, 进入到/etc/sysconfig/network-scripts/目录,找到ifcgf-p2p2文件,打开是这个样子的:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=no
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=p2p2
UUID=0a69226b-6051-4cb4-a1d3-17f37896275a
DEVICE=p2p2
ONBOOT=no
GATEWAY=192.168.11.1
IPADDR=192.168.11.111
NETMASK=255.255.255.0
DNS=114.114.114.114

我们直接在里面增加需要添加的IP,如下所示:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=no
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=p2p2
UUID=0a69226b-6051-4cb4-a1d3-17f37896275a
DEVICE=p2p2
ONBOOT=no
GATEWAY=192.168.11.1
IPADDR=192.168.11.111
NETMASK=255.255.255.0
DNS=114.114.114.114
IPADDR2=192.168.11.11
GATEWAY2=192.168.11.1
NETMASK2=255.255.255.0
DNS2=114.114.114.114
IPADDR3=192.168.11.12
GATEWAY3=192.168.11.1
NETMASK3=255.255.255.0
DNS3=114.114.114.114

如上图,我们增加了两个IP, 一个为192.168.11.11,一个为192.168.11.12

保存后将网卡重新上线一下:

[root@ck10 chenyc]#ifdown p2p2
[root@ck10 chenyc]#ifup p2p2

完成后,从ifcofig是看不出来的:

[root@ck10 chenyc]# ifconfig p2p2
p2p2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.11.111  netmask 255.255.255.0  broadcast 192.168.11.255
        inet6 fe80::cd7f:92f2:deb5:fb14  prefixlen 64  scopeid 0x20<link>
        ether 90:e2:ba:8f:06:41  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 232  bytes 47704 (46.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

但是用ip a命令可以看到已经生效:

7: p2p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 90:e2:ba:8f:06:41 brd ff:ff:ff:ff:ff:ff
    inet 192.168.11.111/24 brd 192.168.11.255 scope global noprefixroute p2p2
       valid_lft forever preferred_lft forever
    inet 192.168.11.11/24 brd 192.168.11.255 scope global secondary noprefixroute p2p2
       valid_lft forever preferred_lft forever
    inet 192.168.11.12/24 brd 192.168.11.255 scope global secondary noprefixroute p2p2
       valid_lft forever preferred_lft forever
    inet6 fe80::cd7f:92f2:deb5:fb14/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

C代码实现

Linux 下获取单网卡的多IP实现方法有很多,我这里演示两种实现方法。

方法一

#include <stdio.h>
#include <stdlib.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/if.h>
#include<string.h>
int main(int argc, char **argv) {
    struct ifaddrs *ifaddr, *ifa;
    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        exit(EXIT_FAILURE);
    }
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == NULL) {
            continue;
        }
        if (strcmp(ifa->ifa_name, "p2p2") == 0 ){
                char ip[64] = {0};
                struct sockaddr_in *sock = ( struct sockaddr_in*)ifa->ifa_addr;
                inet_ntop(AF_INET,&sock->sin_addr, ip, sizeof(ip));
                printf("name: %s, ip: %s\n", ifa->ifa_name, ip);
        }
    }
    freeifaddrs(ifaddr);
    exit(EXIT_SUCCESS);
}

第一种方法主要是利用getifaddrs函数获取到所有的网卡信息,这些信息会返回到一个 struct ifaddrs结构体中,该结构体本身是一个单向链表,结构如下所示:

struct ifaddrs {
               struct ifaddrs  *ifa_next;    /* Next item in list */
               char            *ifa_name;    /* Name of interface */
               unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
               struct sockaddr *ifa_addr;    /* Address of interface */
               struct sockaddr *ifa_netmask; /* Netmask of interface */
               union {
                   struct sockaddr *ifu_broadaddr;
                                    /* Broadcast address of interface */
                   struct sockaddr *ifu_dstaddr;
                                    /* Point-to-point destination address */
               } ifa_ifu;
           #define              ifa_broadaddr ifa_ifu.ifu_broadaddr
           #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
               void            *ifa_data;    /* Address-specific data */
           };

其中,ifa_next存储的是下一条网卡信息的地址,ifa_name存储的是网卡名,ifa_addr存储的就是IP地址。

不过这个函数会获取到一些冗余的信息,这些信息并不是我们所需要的,上面代码运行结果如下所示:

[root@ck10 chenyc]# ./1
name: p2p2, ip: 7.0.0.0
name: p2p2, ip: 192.168.11.111
name: p2p2, ip: 192.168.11.11
name: p2p2, ip: 192.168.11.12
name: p2p2, ip: 0.0.0.0

多了一个7.0.0.00.0.0.0

方法二

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <linux/if.h>
#include<stdio.h> 
#define BUF_SIZE 1024
int main()
{
    int sock_fd;
    struct ifconf conf;
    struct ifreq *ifr;
    char buff[BUF_SIZE] = {0};
    int num;
    int i;
    sock_fd = socket(PF_INET, SOCK_DGRAM, 0);
    if ( sock_fd < 0 )     
        return -1;
    conf.ifc_len = BUF_SIZE;
    conf.ifc_buf = buff;
    if ( ioctl(sock_fd, SIOCGIFCONF, &conf) < 0 )
    {
        close(sock_fd);
        return -1;
    }
    num = conf.ifc_len / sizeof(struct ifreq);
    ifr = conf.ifc_req;
    for(i = 0; i < num; i++)
    {
        struct sockaddr_in *sin = (struct sockaddr_in *)(&ifr->ifr_addr);
        if ( ioctl(sock_fd, SIOCGIFFLAGS, ifr) < 0 )
        {
                close(sock_fd);
                return -1;
        }
        if ( (ifr->ifr_flags & IFF_UP) && strcmp("p2p2",ifr->ifr_name) == 0 )
        {
             printf("ip: %s\n", inet_ntoa(sin->sin_addr));
        }
        ifr++;
    }
    close(sock_fd);
    return -1;
}

这段代码的逻辑就好理解得多。直接调用ioctl接口,先用SIOCGIFCONF获取到所有的网卡,然后再用SIOCGIFFLAGS依次拿到各个网卡的信息即可。这样子取出来的数据就是我们需要的结果。

上面代码运行结果如下:

[root@ck10 chenyc]# ./2
ip: 192.168.11.111
ip: 192.168.11.11
ip: 192.168.11.12

推荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,

fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,

TCP/IP,协程,DPDK等技术内容,点击立即学习: C/C++Linux服务器开发/高级架构师

目录
相关文章
|
4月前
|
Ubuntu Linux 网络安全
在Linux云服务器上限制特定IP进行SSH远程连接的设置
温馨提示,修改iptables规则时要格外小心,否则可能导致无法远程访问你的服务器。最好在掌握足够技术知识和理解清楚操作含义之后再进行。另外,在已经配置了防火墙的情况下,例如ufw(Ubuntu Firewall)或firewalld,需要按照相应的防火墙的规则来设置。
194 24
|
5月前
|
安全 Linux
阿里云linux服务器使用脚本通过安全组屏蔽异常海外访问ip
公网网站可能会遭受黑客攻击导致访问异常,使用此脚本可以屏蔽掉异常IP 恢复访问。也可自行设置定时任务定期检测屏蔽。
438 28
|
5月前
|
JavaScript Linux Python
在Linux服务器中遇到的立即重启后的绑定错误:地址已被使用问题解决
总的来说,解决"地址已被使用"的问题需要理解Linux的网络资源管理机制,选择合适的套接字选项,以及合适的时间点进行服务重启。以上就是对“立即重启后的绑定错误:地址已被使用问题”的全面解答。希望可以帮你解决问题。
321 20
|
5月前
|
人工智能 Kubernetes Ubuntu
linux配置IP
linux配置IP
501 1
|
8月前
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
310 11
|
监控 网络协议 Linux
在Linux中,如何查看某个网卡是否连接着交换机?
在Linux中,如何查看某个网卡是否连接着交换机?
|
11月前
|
Web App开发 资源调度 网络协议
Linux系统之部署IP工具箱MyIP
【10月更文挑战第5天】使用Docker部署Radicale日历和联系人应用Linux系统之部署IP工具箱MyIP
425 1
Linux系统之部署IP工具箱MyIP
|
10月前
|
缓存 网络协议 Linux
Linux ip命令常用操作
Linux的 `ip`命令是一个强大且灵活的网络管理工具,能够执行从基本的网络接口配置到高级的路由和VLAN管理等多种操作。通过熟练掌握这些常用操作,用户可以更加高效地管理和配置Linux系统的网络环境。无论是在日常管理还是故障排除中,`ip`命令都是必不可少的工具。
201 2
|
11月前
|
存储 编译器 C语言
C语言:数组名作为类型、作为地址、对数组名取地址的区别
在C语言中,数组名可以作为类型、地址和取地址使用。数组名本身代表数组的首地址,作为地址时可以直接使用;作为类型时,用于声明指针或函数参数;取地址时,使用取地址符 (&),得到的是整个数组的地址,类型为指向该类型的指针。
|
11月前
|
存储 C语言
C语言:设置地址为 0x67a9 的整型变量的值为 0xaa66
在C语言中,可以通过指针操作来实现对特定地址的访问和赋值。要将地址为 0x67a9 的整型变量值设为 0xaa66,可以先定义一个指向该地址的指针,并通过该指针对该内存位置进行赋值操作。需要注意的是,直接操作内存地址具有一定风险,必须确保地址合法且可写。代码示例应考虑字节序及内存对齐问题。

热门文章

最新文章