获取网络上活动IP的列表(Linux)

Get list of alive IP on network (Linux)

本文关键字:列表 Linux IP 网络 活动 获取      更新时间:2023-10-16

我有一个很好的小程序,它给了我一个系统连接到的网络上所有活动ip的向量。。。但仅适用于windows

std::vector<std::string> resultIPList;
PMIB_IPNET_TABLE2 pipTable = NULL;
unsigned long status = GetIpNetTable2(AF_INET, &pipTable);
if(status != NO_ERROR)
{
    LOG_ERROR("Error in getting ip Table")
    return resultIPList;
}
for(unsigned i = 0; i < pipTable->NumEntries; i++)
{
    char* ip = inet_ntoa(pipTable->Table[i].Address.Ipv4.sin_addr);
    std::string str = std::string(ip);
    resultIPList.push_back(str);
}
FreeMibTable(pipTable);
pipTable = NULL;
return resultIPList;  

在Linux中有没有同样的方法(替换GetIpNetTable函数)。我正在使用RHEL

getifaddrs FTW

#include <ifaddrs.h>
#include <net/if.h>
#include <netinet/in.h>
#include <cstdlib>
ifaddrs* pAdapter = NULL;
ifaddrs* pList = NULL;
int result = getifaddrs(&pList);
if (result == -1)
   return;
pAdapter = pList;
while (pAdapter)
{
    if ((pAdapter->ifa_addr != NULL) && (pAdapter->ifa_flags & IFF_UP))
    {
        if (pAdapter->ifa_addr->sa_family == AF_INET)
        {
            sockaddr_in* addr = (sockaddr_in*)(pAdapter->ifa_addr);
        }
        else if (pAdapter->ifa_addr->sa_family == AF_INET6)
        {
            sockaddr_in6* addr6 = (sockaddr_in6*)(pAdapter->ifa_addr);
        }
    }
    pAdapter = pAdapter->ifa_next;
}
freeifaddrs(pList);
pList = NULL;

我想看看RHEL上的rtnetlink和getifaddrs,还有NetworkManager,这三者都应该允许您所寻找的东西,但我不认为这三者中的任何一个是特定于windows的API的直接替代品。您还必须有一些方法来破解代码,以便编译相关的函数。我通常使用"#ifndef"来拆分代码,这样你就可以让相同的代码返回相同的东西,但使用不同的代码体,这取决于你编译的目标操作系统。

我最近回答了另一个问题,其中windows/linux编译是一个问题(用于查找boost的运行时版本)这里,原理保持不变,可以轻松地根据您的需求进行定制。

顺便说一句,我怀疑Boost.Asio可能也会在Windows和Linux中为您提供一点帮助。您也可以将其作为与Boost的集成版本或独立版本,以实现更小的占地面积。

让我知道你的进展,或者如果你需要更多信息:)

附录

在Linux上,您可以使用以下内容:

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
void
print_sockaddr(struct sockaddr* addr,const char *name)
{
    char addrbuf[128] ;
    addrbuf[0] = 0;
    if(addr->sa_family == AF_UNSPEC)
        return;
    switch(addr->sa_family) {
        case AF_INET:
            inet_ntop(addr->sa_family,&((struct sockaddr_in*)addr)->sin_addr,addrbuf,sizeof(addrbuf));
            break;
        case AF_INET6:
            inet_ntop(addr->sa_family,&((struct sockaddr_in6*)addr)->sin6_addr,addrbuf,sizeof(addrbuf));
            break;
        default:
            sprintf(addrbuf,"Unknown (%d)",(int)addr->sa_family);
            break;
    }
    printf("%-16s %sn",name,addrbuf);
}
void
print_ifaddr(struct ifaddrs *addr)
{
    char addrbuf[128] ;
    addrbuf[0] = 0;
    printf("%-24s %sn","Interface Name:",addr->ifa_name);
    if(addr->ifa_addr != NULL)
        print_sockaddr(addr->ifa_addr,"Interface Address:");
    if(addr->ifa_netmask != NULL)
        print_sockaddr(addr->ifa_netmask,"Netmask:");
    if(addr->ifa_broadaddr != NULL)
        print_sockaddr(addr->ifa_broadaddr,"Broadcast address:");
    if(addr->ifa_dstaddr != NULL)
        print_sockaddr(addr->ifa_dstaddr,"Peer address:");
    puts("");
}
int main(int argc,char *argv[])
{
    struct ifaddrs *addrs,*tmp;
    if(getifaddrs(&addrs) != 0) {
        perror("getifaddrs");
        return 1;
    }
    for(tmp = addrs; tmp ; tmp = tmp->ifa_next) {
        print_ifaddr(tmp);
    }
    freeifaddrs(addrs);
    return 0;
}

对于其他衍生产品(Unix、BSD等),这组更基本的代码可能更有用,尽管我模糊地记得BSD下的一些问题(对不起,目前记不清具体是什么,认为这与某些条件会使其无法运行的失败场景有关)

#include <stdio.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#define INT_TO_ADDR(_addr) 
(_addr & 0xFF), 
(_addr >> 8 & 0xFF), 
(_addr >> 16 & 0xFF), 
(_addr >> 24 & 0xFF)
int main()
{
    struct ifconf ifc;
    struct ifreq ifr[10];
    int sd, ifc_num, addr, bcast, mask, network, i;
    // Create a socket then use ioctl on the file descriptor to retrieve the interface information.
    sd = socket(PF_INET, SOCK_DGRAM, 0);
    if (sd > 0)
    {
        ifc.ifc_len = sizeof(ifr);
        ifc.ifc_ifcu.ifcu_buf = (caddr_t)ifr;
        if (ioctl(sd, SIOCGIFCONF, &ifc) == 0)
        {
            ifc_num = ifc.ifc_len / sizeof(struct ifreq);
            printf("%d interfaces found.n", ifc_num);
            for (i = 0; i < ifc_num; ++i)
            {
                if (ifr[i].ifr_addr.sa_family != AF_INET)
                {
                    continue;
                }
                /* display the interface name */
                printf("%d) Interface Name: %sn", i+1, ifr[i].ifr_name);
                /* Retrieve the IP address, broadcast address, and subnet mask. */
                if (ioctl(sd, SIOCGIFADDR, &ifr[i]) == 0)
                {
                    addr = ((struct sockaddr_in *)(&ifr[i].ifr_addr))->sin_addr.s_addr;
                    printf("%d) Interface address: %d.%d.%d.%dn", i+1, INT_TO_ADDR(addr));
                }
                if (ioctl(sd, SIOCGIFBRDADDR, &ifr[i]) == 0)
                {
                    bcast = ((struct sockaddr_in *)(&ifr[i].ifr_broadaddr))->sin_addr.s_addr;
                    printf("%d) Broadcast: %d.%d.%d.%dn", i+1, INT_TO_ADDR(bcast));
                }
                if (ioctl(sd, SIOCGIFNETMASK, &ifr[i]) == 0)
                {
                    mask = ((struct sockaddr_in *)(&ifr[i].ifr_netmask))->sin_addr.s_addr;
                    printf("%d) Netmask: %d.%d.%d.%dn", i+1, INT_TO_ADDR(mask));
                }                
                /* Compute the current network value from the address and netmask. */
                network = addr & mask;
                printf("%d) Current Network: %d.%d.%d.%dn", i+1, INT_TO_ADDR(network));
            }                      
        }
        close(sd);
    }
    return 0;
}

显然,您需要定制代码以满足您的需求,但这可能会有所帮助:)