getifaddrs()和struct ifaddrs的使用,获取本机IP

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是接口名称,以0结尾的字符串,比如eth0,lo;ifa_flags是接口的标识位(比如当IFF_BROADCAST或IFF_POINTOPOINT设置到此标识位时,影响联合体变量ifu_broadaddr存储广播地址或ifu_dstaddr记录点对点地址);ifa_netmask存储该接口的子网掩码;结构体变量存储广播地址或点对点地址(见括弧介绍ifa_flags);ifa_data存储了该接口协议族的特殊信息,它通常是NULL(一般不关注他)。

函数getifaddrs(int getifaddrs (struct ifaddrs **__ifap))获取本地网络接口信息,将之存储于链表中,链表头结点指针存储于__ifap中带回,函数执行成功返回0,失败返回-1,且为errno赋值。
    很显然,函数getifaddrs用于获取本机接口信息,比如最典型的获取本机IP地址。

linux编程获取本机IP地址的三种方法

这 是一项不太清晰而且没有多大意义的工作。一个原因是网络地址的设置非常灵活而且都是允许用户进行个性化设置的,比如一台计算机上可以有多块物理网卡或者虚 拟网卡,一个网卡上可以绑定多个IP地址,用户可以为网卡设置别名,可以重命名网卡,用户计算机所在网络拓扑结构未知,主机名设置是一个可选项并且同样可 以为一个计算机绑定多个主机名等,这些信息都会有影响。脱离了网络连接,单独的网络地址没有任何意义。编程中遇到必须获取计算机IP的场景,应该考虑将这 一选项放到配置文件中,由用户自己来选择。

通过google,编程获取IP地址大约有以下三种思路:
. 通过gethostname()和gethostbyname() #include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> int main() {
char hname[];
struct hostent *hent;
int i; gethostname(hname, sizeof(hname)); //hent = gethostent();
hent = gethostbyname(hname); printf("hostname: %s/naddress list: ", hent->h_name);
for(i = ; hent->h_addr_list[i]; i++) {
printf("%s/t", inet_ntoa(*(struct in_addr*)(hent->h_addr_list[i])));
}
return ;
} 运行:
[whb@jcwkyl c]$ ./local_ip
hostname: jcwkyl.jlu.edu.cn
address list: 10.60.56.90 . 通过枚举网卡,API接口可查看man netdevice /*代码来自StackOverflow: http://stackoverflow.com/questions/212528/linux-c-get-the-ip-address-of-local-computer */
#include <stdio.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h> int main (int argc, const char * argv[]) {
struct ifaddrs * ifAddrStruct=NULL;
void * tmpAddrPtr=NULL; getifaddrs(&ifAddrStruct); while (ifAddrStruct!=NULL) {
if (ifAddrStruct->ifa_addr->sa_family==AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
printf("%s IP Address %s/n", ifAddrStruct->ifa_name, addressBuffer);
} else if (ifAddrStruct->ifa_addr->sa_family==AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
printf("%s IP Address %s/n", ifAddrStruct->ifa_name, addressBuffer);
}
ifAddrStruct=ifAddrStruct->ifa_next;
}
return ;
} 运行 :
[whb@jcwkyl c]$ ./local_ip2
lo IP Address 127.0.0.1
eth0 IP Address 10.60.56.90
eth0: IP Address 192.168.1.3
lo IP Address ::
eth0 IP Address :::da8:b000::20f:1fff
eth0 IP Address ::fe80::20f:1fff . 打开一个对外界服务器的网络连接,通过getsockname()反查自己的IP

linux下获取IP等信息函数

在linux下 获取,修改本机IP地址的两个函数

//获取本机IP地址函数

 QString GetLocalIp()
{ int sock_get_ip;
char ipaddr[]; struct sockaddr_in *sin;
struct ifreq ifr_ip; if ((sock_get_ip=socket(AF_INET, SOCK_STREAM, )) == -)
{
printf("socket create failse...GetLocalIp!/n");
return "";
} memset(&ifr_ip, , sizeof(ifr_ip));
strncpy(ifr_ip.ifr_name, "eth0", sizeof(ifr_ip.ifr_name) - ); if( ioctl( sock_get_ip, SIOCGIFADDR, &ifr_ip) < )
{
return "";
}
sin = (struct sockaddr_in *)&ifr_ip.ifr_addr;
strcpy(ipaddr,inet_ntoa(sin->sin_addr)); printf("local ip:%s /n",ipaddr);
close( sock_get_ip ); return QString( ipaddr );
}

//修改本机IP地址的函数

 int SetLocalIp( const char *ipaddr )
{ int sock_set_ip; struct sockaddr_in sin_set_ip;
struct ifreq ifr_set_ip; bzero( &ifr_set_ip,sizeof(ifr_set_ip)); if( ipaddr == NULL )
return -; if(sock_set_ip = socket( AF_INET, SOCK_STREAM, ) == -);
{
perror("socket create failse...SetLocalIp!/n");
return -;
} memset( &sin_set_ip, , sizeof(sin_set_ip));
strncpy(ifr_set_ip.ifr_name, "eth0", sizeof(ifr_set_ip.ifr_name)-); sin_set_ip.sin_family = AF_INET;
sin_set_ip.sin_addr.s_addr = inet_addr(ipaddr);
memcpy( &ifr_set_ip.ifr_addr, &sin_set_ip, sizeof(sin_set_ip)); if( ioctl( sock_set_ip, SIOCSIFADDR, &ifr_set_ip) < )
{
perror( "Not setup interface/n");
return -;
} //设置激活标志
ifr_set_ip.ifr_flags |= IFF_UP |IFF_RUNNING; //get the status of the device
if( ioctl( sock_set_ip, SIOCSIFFLAGS, &ifr_set_ip ) < )
{
perror("SIOCSIFFLAGS");
return -;
} close( sock_set_ip );
return ;
}

在linux下 获取本机MAC地址的函数

获取本机MAC地址函数

 QString GetLocalMac()
{
int sock_mac; struct ifreq ifr_mac;
char mac_addr[]; sock_mac = socket( AF_INET, SOCK_STREAM, );
if( sock_mac == -)
{
perror("create socket falise...mac/n");
return "";
} memset(&ifr_mac,,sizeof(ifr_mac));
strncpy(ifr_mac.ifr_name, "eth0", sizeof(ifr_mac.ifr_name)-); if( (ioctl( sock_mac, SIOCGIFHWADDR, &ifr_mac)) < )
{
printf("mac ioctl error/n");
return "";
} sprintf(mac_addr,"%02x%02x%02x%02x%02x%02x",
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[],
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[],
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[],
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[],
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[],
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[]); printf("local mac:%s /n",mac_addr); close( sock_mac );
return QString( mac_addr );
}

在linux下 获取,修改子网掩码NETMASK的两个函数

//获取子网掩码的函数

 QString GetLocalNetMask()
{
int sock_netmask;
char netmask_addr[]; struct ifreq ifr_mask;
struct sockaddr_in *net_mask; sock_netmask = socket( AF_INET, SOCK_STREAM, );
if( sock_netmask == -)
{
perror("create socket failture...GetLocalNetMask/n");
return "";
} memset(&ifr_mask, , sizeof(ifr_mask));
strncpy(ifr_mask.ifr_name, ifname, sizeof(ifr_mask.ifr_name )-); if( (ioctl( sock_netmask, SIOCGIFNETMASK, &ifr_mask ) ) < )
{
printf("mac ioctl error/n");
return "";
} net_mask = ( struct sockaddr_in * )&( ifr_mask.ifr_netmask );
strcpy( netmask_addr, inet_ntoa( net_mask -> sin_addr ) ); printf("local netmask:%s/n",netmask_addr); close( sock_netmask );
return QString( netmask_addr );
}

//修改子NETMASK的函数

 QString SetLocalNetMask(const char *szNetMask)
{
int sock_netmask;
char netmask_addr[]; struct ifreq ifr_mask;
struct sockaddr_in *sin_net_mask; sock_netmask = socket( AF_INET, SOCK_STREAM, );
if( sock_netmask == -)
{
perror("Not create network socket connect/n");
return "";
} memset(&ifr_mask, , sizeof(ifr_mask));
strncpy(ifr_mask.ifr_name, "eth0", sizeof(ifr_mask.ifr_name )-);
sin_net_mask = (struct sockaddr_in *)&ifr_mask.ifr_addr;
sin_net_mask -> sin_family = AF_INET;
inet_pton(AF_INET, szNetMask, &sin_net_mask ->sin_addr); if(ioctl(sock_netmask, SIOCSIFNETMASK, &ifr_mask ) < )
{
printf("sock_netmask ioctl error/n");
return "";
}
}

//获去GateWay

 QString GetGateWay()
{
FILE *fp;
char buf[];
char cmd[];
char gateway[];
char *tmp; strcpy(cmd, "ip route");
fp = popen(cmd, "r");
if(NULL == fp)
{
perror("popen error");
return "";
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
tmp =buf;
while(*tmp && isspace(*tmp))
++ tmp;
if(strncmp(tmp, "default", strlen("default")) == )
break;
}
sscanf(buf, "%*s%*s%s", gateway);
printf("default gateway:%s/n", gateway);
pclose(fp); return QString(gateway);
}

//设置网关

 int SetGateWay(const char *szGateWay)
{
int ret = ;
char cmd[];
QString DefGW = GetGateWay(); const char *strGW = DefGW.latin1(); strcpy(cmd, "route del default gw ");
strcat(cmd, strGW);
ret = system(cmd);
if(ret < )
{
perror("route error");
return -;
}
strcpy(cmd, "route add default gw ");
strcat(cmd, szGateWay); ret = system(cmd);
if(ret < )
{
perror("route error");
return -;
} return ret;
}

Linux下如何获取网卡信息

有时候,写程序的时候需要获取计算机的网络信息,比如IP地址、电脑名称、DNS等信息。IP地址和电脑名称是比较容易获取到的,而要想获取地址掩码、DNS、网关等信息就有些麻烦了。

在Windows下我们一般都是通过从注册表读取这些信息。在Linux怎么做呢?其实,Linux下更加容易一些。因为我们可以拿现成的程序看它的源代码。通过阅读其源代码找到解决该问题的方法。那么,看哪个程序的源代码呢?如果你使用过Linux,并且比较熟悉的话就肯定知道一个命令ifconfig。这个命令和Windows下的ipconfig差不多,都可以输出网卡的信息,其中就包含DNS、掩码等信息。所以,我们可以通过看它的源代码来找到解决该问题的方法。

获取系统中的网卡数量

并没有那个系统调用提供网卡数量的获取。但是,我们可以通过强大的proc文件系统获取网卡数量的信息。实际上,ifconfig也是这样做的,请看示例代码如下: 
 #include <stdio.h>
#include <string.h>
#include <errno.h> int GetNetCardCount()
{
int nCount = ;
FILE* f = fopen("/proc/net/dev", "r");
if (!f)
{
fprintf(stderr, "Open /proc/net/dev failed!errno:%d\n", errno);
return nCount;
} char szLine[]; fgets(szLine, sizeof(szLine), f); /* eat line */
fgets(szLine, sizeof(szLine), f); while(fgets(szLine, sizeof(szLine), f))
{
char szName[] = {};
sscanf(szLine, "%s", szName);
int nLen = strlen(szName);
if (nLen <= )continue;
if (szName[nLen - ] == ':') szName[nLen - ] = ;
if (strcmp(szName, "lo") == )continue;
nCount++;
} fclose(f);
f = NULL;
return nCount;
} int main(int argc, char* argv[])
{
printf("NetCardCount: %d\n", GetNetCardCount());
return ;
}

获取IP、掩码、MAC及网关

获取IP、掩码、MAC和广播地址是比较容易的,只需要调用对应的IOCTL即可。只是大家对Linux下的IOCTL可能不太熟悉。却看示例代码:

 void DispNetInfo(const char* szDevName)
{
int s = socket(AF_INET, SOCK_DGRAM, );
if (s < )
{
fprintf(stderr, "Create socket failed!errno=%d", errno);
return;
} struct ifreq ifr;
unsigned char mac[];
unsigned long nIP, nNetmask, nBroadIP; printf("%s:\n", szDevName); strcpy(ifr.ifr_name, szDevName);
if (ioctl(s, SIOCGIFHWADDR, &ifr) < )
{
return;
}
memcpy(mac, ifr.ifr_hwaddr.sa_data, sizeof(mac));
printf("\tMAC: %02x-%02x-%02x-%02x-%02x-%02x\n",
mac[], mac[], mac[], mac[], mac[], mac[]); strcpy(ifr.ifr_name, szDevName);
if (ioctl(s, SIOCGIFADDR, &ifr) < )
{
nIP = ;
}
else
{
nIP = *(unsigned long*)&ifr.ifr_broadaddr.sa_data[];
}
printf("\tIP: %s\n", inet_ntoa(*(in_addr*)&nIP)); strcpy(ifr.ifr_name, szDevName);
if (ioctl(s, SIOCGIFBRDADDR, &ifr) < )
{
nBroadIP = ;
}
else
{
nBroadIP = *(unsigned long*)&ifr.ifr_broadaddr.sa_data[];
}
printf("\tBroadIP: %s\n", inet_ntoa(*(in_addr*)&nBroadIP)); strcpy(ifr.ifr_name, szDevName);
if (ioctl(s, SIOCGIFNETMASK, &ifr) < )
{
nNetmask = ;
}
else
{
nNetmask = *(unsigned long*)&ifr.ifr_netmask.sa_data[];
}
printf("\tNetmask: %s\n", inet_ntoa(*(in_addr*)&nNetmask));
close(s);
}

那么如何获取网关地址呢?更加容易,但是,好像很少有人知道。反正我在网上没有找到有人知道。最后看了nslookup的源代码以后才知道正确的做法。代码如下:

  res_init();      

        for (int i = ; i < _res.nscount; i++)

        {

               struct sockaddr* server = (struct sockaddr*)&_res.nsaddr_list[i];

               printf("Server:  %s\n", inet_ntoa(*(in_addr*)&(server->sa_data[])));

        }

代码很简单,就不做解释了。

怎么获取网关呢?这个稍微有点麻烦一些,不过和获取网卡数量相似,都是通过proc文件系统。这次分析的/proc/net/route文件。我就不再贴出示例代码了。

最后,我把运行示例程序获取到的信息附上,以供大家有个直观的认识:

eth0:

       MAC: ----bf-f3

       IP: 192.168.1.106

       BroadIP: 255.255.255.255

       Netmask: 255.255.255.0

Gateway: 192.168.1.1

eth1:

       MAC: ----f4-bf

       IP: 192.168.1.108

       BroadIP: 192.168.1.255

       Netmask: 255.255.255.0

Gateway: 0.0.0.0

eth2:

       MAC: ----9c-

       IP: 0.0.0.0

       BroadIP: 0.0.0.0

       Netmask: 0.0.0.0

Gateway: 0.0.0.0

eth3:

       MAC: ---5a-d2-

       IP: 0.0.0.0

       BroadIP: 0.0.0.0

       Netmask: 0.0.0.0

Gateway: 0.0.0.0

NetCardCount: 

DNS :  218.2.135.1

DNS :  61.147.37.1

Linux下C语言配置网络与获取网络配置信息的方法

Linux下的网络配置包含三个要素,分别是IP地址、子网掩码和网关。本文将介绍如何在C语言中进行网络的配置和配置信息的获取。

【配置】

方法一

使用system()或exec*()调用ifconfig和route命令进行配置。这种方法的优点是使用简单,缺点是效率比较低,且依赖于ifconfig与route命令。

示例:

见所附代码中的函数ip_config_system()和ip_config_exec()。

方法二

建立一个socket,用ioctl()进行配置。这种方法的优点是效率较高,缺点是程序实现起来比较麻烦。

示例:

见所附代码中的函数ip_config_ioctl()。

【获取】

方法一

用popen()建立一个管道,管道的一端执行命令ifconfig和route,管道的另一端读取收到的数据并进行相应的解析。这种方法的优点是使用简单,缺点是效率比较低,且依赖于ifconfig与route命令。

示例:

见所附代码中的函数ip_get_pipe()。

方法二

用fopen()打开/proc/net/route,可以获取网关(在/proc/net中尚未发现比较好的获取IP地址和掩码的方法,知道的请发邮件至cugfeng at gamil.com,谢谢)。这种方法的优点是使用简单,效率比执行命令高,缺点是依赖于proc文件系统。

示例:

见所附代码中的函数ip_get_proc()。

方法三

建立一个socket,用ioctl()进行获取(用ioctl()尚未发现比较好的获取网关的方法,知道的请发邮件至cugfeng at gamil.com,谢谢)。这种方法的优点是效率较高,缺点是程序实现起来比较麻烦。

示例:

见所附代码中的函数ip_get_ioctl()。

BTW,用ioctl()的方法还可以获取MAC地址,ioctl()命令为SIOCGIFHWADDR,具体用法与ioctl()获取IP地址的方法相同,这里就不多说了。

Linux 获取本机IP、MAC地址用法大全的更多相关文章

  1. JAVA获取本机的MAC地址

    /** * 获取本机的Mac地址 * @return */ public String getMac() { InetAddress ia; byte[] mac = null; try { // 获 ...

  2. Delphi获取本机的MAC地址

    Delphi获取本机的MAC地址: uses   NB30; function GetAdaPterInfo(lana: Char): string; var   Adapter: TAdapterS ...

  3. java 获取计算机名称, ip, mac地址

    写在前面 通常所说查询本机mac地址是以以太网为准的, 也就是网线那个口..这种描述略捞. 但是通过java的getHostAddress获取ip以及getHardwareAddress()方法获取m ...

  4. C#获取本机的MAC地址

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.M ...

  5. linux获取本机ip

    int get_ip ( in_addr_t addrs[], int asize  ) {         int MAXINTERFACES=16;         int i = 0;     ...

  6. [记]WIndow/Linux 获取本机(全部)IPv4、IPv6、MAC地址方法 (C/C++)

    Linux 获取本机IP.MAC地址用法大全 //#include <sys/types.h> #include <ifaddrs.h> #include <sys/io ...

  7. QT5下获取本机IP地址、计算机名、网络连接名、MAC地址、子网掩码、广播地址

    获取主机名称 /* * 名称:get_localmachine_name * 功能:获取本机机器名称 * 参数:no * 返回:QString */ QString CafesClient::get_ ...

  8. JAVA获取本机IP和Mac地址

       在项目中,时常需要获取本机的Ip或是Mac地址,进行身份和权限验证,本文就是通过java代码获取ip和Mac. package com.svse.query;import java.net.In ...

  9. 获取本机IP、mac地址、计算机名

    python获取本机IP.mac地址.计算机名 在python中获取ip地址和在php中有很大不同,我们先来看一下python 获得本机MAC地址: >>> import uuid ...

随机推荐

  1. Uva 12171 Sculpture - 离散化 + floodfill

    题目连接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  2. SQL作业及调度创建

    转自:http://www.cnblogs.com/accumulater/p/6223909.html --定义创建作业 转自http://hi.baidu.com/procedure/blog/i ...

  3. Asp.net mvc 中的 Controller 的激活

    Controller 激活是指根据路由系统解析出来的 Controller 的名称创建 控制器(Controller)的过程,这里的控制器泛指实现了 IController 接口的类型 激活过程中的核 ...

  4. python生产随机数案例

    法1: list =list(string.lowercase + string.uppercase) + [str(i) for i in range(10)]FH=('!','@','#','$' ...

  5. 关于今天esp8266运行失控问题和oled与串口共存尝试成功的总结

    今天2017-12-1720:24:22下午esp8266再次无法刷入固件,导致我一度崩溃,本来已经认为esp8266已经相当稳定了,没想到今天又运行出错,总结如下 今天2017-12-17esp无法 ...

  6. linux_samba服务安装

    什么是samba服务? 用于Windows和linux系统之间实现共享文件的目的服务 如何配置其服务? Linux端: 搭建服务 1. 安装samba yum install -y samba 2. ...

  7. python_协程方式操作数据库

    # !/usr/bin/python3 # -*- coding: utf-8 -*- import requests import gevent import pymysql from gevent ...

  8. Eclipse设置代码自动提示

    Eclipse只需几步简单的设置就可以像idea那样代码自动提示了,喜欢的小伙伴可以赶紧动手设置,提升效率. 第一步:打开Eclipse --> Window --> Preference ...

  9. 【转】CentOS 6.3(x86_32)下安装Oracle 10g R2

    一.硬件要求 1.内存 & swap Minimum: 1 GB of RAMRecommended: 2 GB of RAM or more 检查内存情况 # grep MemTotal / ...

  10. mybatis-spring最新版下载地址

    mybatis-spring最新版下载地址: http://mvnrepository.com/artifact/org.mybatis/mybatis-spring/1.2.3 mybatis-sp ...