Linux编程获取本机IP地址的几种方法

参考:

https://blog.csdn.net/zhongmushu/article/details/89944990

https://www.cnblogs.com/lzpong/p/6956439.html

在进行Linux网络编程时,经常会需要获取本机IP地址,除了常规的读取配置文件外,本文罗列几种个人所知的编程常用方法,仅供参考,如有错误请指出。

方法一:使用ioctl()获取本地IP地址

Linux下可以使用ioctl()函数以及结构体 struct ifreq和结构体struct ifconf来获取网络接口的各种信息。具体过程是先通过ictol获取本地所有接口的信息保存到ifconf结构中,再从其中取出每个ifreq表示的接口信息。

如果本机的IP地址绑定在第一块网卡上,则只需指定网卡名称,无需获取所有网卡的信息即可获取,见如下函数:

int get_localip(const char * eth_name, char *local_ip_addr)
{
int ret = -1;
register int fd;
struct ifreq ifr; if (local_ip_addr == NULL || eth_name == NULL)
{
return ret;
}
if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0)
{
strcpy(ifr.ifr_name, eth_name);
if (!(ioctl(fd, SIOCGIFADDR, &ifr)))
{
ret = 0;
strcpy(local_ip_addr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
}
}
if (fd > 0)
{
close(fd);
}
return ret;
}

如果想通过获取所有网络接口信息,示例代码如下:

#include <stdio.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <netinet/in.h> int get_localip(const char * eth_name, char *local_ip_addr)
{
int ret = -1;
register int fd, intrface;
struct ifreq ifr[32];
struct ifconf ifc; if (local_ip_addr == NULL || eth_name == NULL)
{
return ret;
}
if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) > 0)
{
ifc.ifc_len = sizeof ifr;
ifc.ifc_buf = (caddr_t)ifr;
if (!ioctl(fd, SIOCGIFCONF, (char*)&ifc)) //获取所有接口信息
{
intrface = ifc.ifc_len / sizeof(struct ifreq);
while (intrface-- > 0)
{
//Get IP Address
if (!(ioctl(fd, SIOCGIFADDR, (char*)&ifr[intrface])))
{
if(strcmp(eth_name, ifr[intrface].ifr_name) == 0)
{
ret = 0;
sprintf(local_ip_addr, "%s", inet_ntoa(((struct sockaddr_in*)(&ifr[intrface].ifr_addr))->sin_addr));
break;
}
}
}
}
}
if (fd > 0)
{
close(fd);
}
return ret;
} int main(int argc, const char **argv)
{
int ret;
char local_ip[20] = {0}; ret = get_localip("eth0", local_ip);
if (ret == 0)
{
printf("local ip:%s\n", local_ip);
}
else
{
printf("get local ip failure\n");
}
return 0;
}

方法二:getsockname()获取本地IP地址

getsockname()用于获取一个已捆绑或已连接套接字的本地地址。若一个套接字与INADDR_ANY捆绑,也就是说该套接字可以用任意主机的地址,此时除非调用connect()或accept()来连接,否则getsockname()将不会返回主机IP地址的任何信息。

示例代码:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h> #define PORT 80
#define SERVER_IP "14.215.177.38" int main(int argc, const char **argv)
{
int ret = -1;
socklen_t len;
char buf[30] = {0};
struct sockaddr_in server_addr, local_addr;
int fd = socket(AF_INET, SOCK_STREAM, 0);
//int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd <= 0)
{
printf("fail to creat socket\n");
return -1;
} memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
if(connect(fd, (struct sockaddr*)&server_addr, sizeof(server_addr))<0)
{
printf("connect error!!!\n");
goto end;
}
len = sizeof(local_addr);
memset(&local_addr, 0, sizeof(local_addr));
ret = getsockname(fd, (struct sockaddr*)&local_addr, &len);
if (ret == 0)
{
printf("local ip is %s, local port is %d\n", inet_ntop(AF_INET, &local_addr.sin_addr, buf, sizeof(buf)), ntohs(local_addr.sin_port));
}
else
{
printf("getsockname failed, error=%d\n", errno);
} end:
if (fd)
{
close(fd);
}
return ret;
}

方法三:getaddrinfo()获取本地IP地址

getaddrinfo()可以完成网络主机中主机名和服务名到地址的映射,但是一般不能用来获取本地IP地址,当它用来获取本地IP地址时,返回的一般是127.0.0.1本地回环地址,且该函数仅仅支持IPv4。

示例代码:

#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h> // 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{
int ret;
char host_name[128] = {0};
struct addrinfo *res, *cur;
struct sockaddr_in *addr; if (gethostname(host_name, sizeof(host_name)) < 0)
{
printf("gethostname error\n");
return -1;
}
ret = getaddrinfo(host_name, NULL, NULL, &res);
if (ret != 0)
{
printf("Error: error in getaddrinfo on hostname: %s\n", gai_strerror(ret));
return -1;
}
for(cur = res; cur != NULL; cur = cur->ai_next)
{
if(cur->ai_family == AF_INET)
{
addr = (struct sockaddr_in*)cur->ai_addr;
printf("local ip:%s\n", inet_ntoa(addr->sin_addr));
}
//char host[1024] = {0};
//ret = getnameinfo(cur->ai_addr, cur->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
//if(ret != 0)
//{
// printf("getnameinfo: %s\n", gai_strerror(ret));
//}
//else
//{
// printf("ip: %s\n", host);
//}
}
freeaddrinfo(res);
return 0;
}

方法四:gethostbyname ()获取本地IP地址

gethostbyname()和getaddrinfo()的功能类似,一般用于通过主机名或者服务名,比如域名来获取主机的IP地址。但是要想获取本地IP地址的时候,一般获取的是回环地址127.0.0.1。

示例代码:

#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h> // 获取本地IP时,一般都是127.0.0.1
int main(int argc, const char **argv)
{
int i = 0;
char host_name[128] = {0};
struct hostent *hptr; if (gethostname(host_name, sizeof(host_name)) < 0)
{
printf("gethostname error\n");
return -1;
}
if ((hptr=gethostbyname(host_name)) == NULL)
{
printf("gethostbyname error\n");
return -1;
}
while(hptr->h_addr_list[i] != NULL)
{
printf("hostname: %s\n", hptr->h_name);
printf(" ip: %s\n", inet_ntoa(*(struct in_addr*)hptr->h_addr_list[i]));
i++;
}
return 0;
}

方法五:通过getifaddrs()获取本地IP地址

/*代码来自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;
struct ifaddrs * ifa=NULL;
void * tmpAddrPtr=NULL; getifaddrs(&ifAddrStruct); for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr)
{
continue;
}
if (ifa->ifa_addr->sa_family == AF_INET) // check it is IP4
{
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
else if (ifa->ifa_addr->sa_family == AF_INET6) // check it is IP6
{
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
}
if (ifAddrStruct!=NULL)
{
freeifaddrs(ifAddrStruct);
} return 0;
}

方法六:通过popen()调用ifconfig获取本地IP地址

用popen()建立一个管道,管道的一端执行命令ifconfig,管道的另一端读取收到的数据并进行相应的解析。这种方法需要执行shell命令,配合正则表达式,效率较低,一般不采用。而这种方式其实更倾向于配置,原因就是使用简单。

示例代码:

#include <stdio.h>
#include <stdlib.h> #define ETH_NAME "ens33" int main(int argc, const char *argv[])
{
FILE *fp;
char buf[256] = {0};
char command[256] = {0};
//char *fmt = "ifconfig %s|sed -n '2p'|sed -n 's#^.*dr:##gp'|sed -n 's#B.*$##gp'";
char *fmt = "ifconfig %s|grep 'inet addr'|awk '{ print $2}' | awk -F: '{print $2}'"; snprintf(command, sizeof(command), fmt, ETH_NAME);
if((fp = popen(command, "r")) == NULL)
{
perror("Fail to popen\n");
return -1;
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
printf("%s", buf);
} pclose(fp);
return 0;
}

方法七:获取所有ip(ipv4+ipv6)

//#include <sys/types.h>
#include <ifaddrs.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
//#include <sys/socket.h>
//#include <netinet/in.h>
#include <arpa/inet.h>
void pHx(unsigned char* p,int len){
printf("Hex: ");
for(int i=0;i<len;i++){
printf("%02X:",p[i]);
}
printf("\b\n");
}
char* getMac(char* mac,char* dv){
struct ifreq ifreq;
int sock;
if(!mac || !dv)
return mac;
if((sock=socket(AF_INET,SOCK_STREAM,0)) <0)
{
perror( "socket ");
return mac;
}
strcpy(ifreq.ifr_name,dv);
if(ioctl(sock,SIOCGIFHWADDR,&ifreq) <0)
{
perror( "ioctl ");
return mac;
}
pHx((unsigned char*)ifreq.ifr_hwaddr.sa_data,sizeof(ifreq.ifr_hwaddr.sa_data));
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", //以太网MAC地址的长度是48位
(unsigned char)ifreq.ifr_hwaddr.sa_data[0],
(unsigned char)ifreq.ifr_hwaddr.sa_data[1],
(unsigned char)ifreq.ifr_hwaddr.sa_data[2],
(unsigned char)ifreq.ifr_hwaddr.sa_data[3],
(unsigned char)ifreq.ifr_hwaddr.sa_data[4],
(unsigned char)ifreq.ifr_hwaddr.sa_data[5]);
return mac;
} int main (int argc, const char * argv[])
{
char hname[128];
struct hostent *hent;
int i; gethostname(hname, sizeof(hname)); //hent = gethostent();
hent = gethostbyname(hname); printf("hostname: %s\n", hent->h_name);
//----------------------------------------------------------
printf("\n\n"); char mac[30];
struct ifaddrs * ifap0=NULL,*ifap=NULL;
void * tmpAddrPtr=NULL; getifaddrs(&ifap0);
ifap=ifap0;
while (ifap!=NULL) {
if (ifap->ifa_addr->sa_family==AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr=&((struct sockaddr_in *)ifap->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
if(strcmp(addressBuffer,"127.0.0.1")!=0){
printf("%s IPv4: %s\n", ifap->ifa_name, addressBuffer);
printf("MAC: %s\n\n",getMac(mac,ifap->ifa_name));
}
} else if (ifap->ifa_addr->sa_family==AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr=&((struct sockaddr_in *)ifap->ifa_addr)->sin_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
if(strcmp(addressBuffer,"::")!=0){
printf("%s IPv6: %s\n", ifap->ifa_name, addressBuffer);
printf("MAC: %s\n\n",getMac(mac,ifap->ifa_name));
}
}
ifap=ifap->ifa_next;
}
if (ifap0) { freeifaddrs(ifap0); ifap0 = NULL; }
return 0;
}

参考文献

[1]https://blog.csdn.net/bailyzheng/article/details/7489656

[2]https://blog.csdn.net/k346k346/article/details/48231933

原文链接:https://blog.csdn.net/zhongmushu/article/details/89944990

LINUX - 获取本地ip的更多相关文章

  1. Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip

    获取本地 ip 地址,mac,通过域名获取对应的 ip, 是网络编程可能遇到的比较常见的操作了,所以总结如下(封装了3个函数), 直接上代码: #include <stdio.h> #in ...

  2. Linux下编程获取本地IP地址的常见方法

    转载于:http://blog.csdn.net/k346k346/article/details/48231933 在进行linux网络编程时,经常用到本机IP地址.本文罗列一下常见方法,以备不时之 ...

  3. Linux编程获取本地IP

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

  4. Android应用开发提高篇(1)-----获取本地IP

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/21/2361802.html 一.概述 习惯了Linux下的网络编程,在还没用智能机之前就一直想 ...

  5. Java获取本地IP地址

    import java.net.InetAddress; import java.net.UnknownHostException; public class IpTest { public stat ...

  6. 获取本地IP地址信息

    2012-06-05    /// <summary>         /// 获取本地IP地址信息         /// </summary>         void G ...

  7. C# — 动态获取本地IP地址及可用端口

    1.在VS中动态获取本地IP地址,代码如下: 2.获取本机的可用端口以及已使用的端口:

  8. .net获取本地ip地址

    整理代码,.net获取本地ip地址,代码如下: string name = Dns.GetHostName(); IPHostEntry IpEntry = Dns.GetHostEntry(name ...

  9. 获取本地IP地址的vc代码

    作者:朱金灿 来源:http://blog.csdn.net/clever101 获取本地IP地址有两种做法.一种是使用gethostname函数,代码如下: bool CSocketComm::Ge ...

随机推荐

  1. 【RAC】运行root.sh的时候报错root.sh Oracle CRS stack is already configured and will be running under init(1M)

    环境:oracle10g 系统:CentOS6.4 开始的时候,在节点1上运行root.sh发现出现90s 的时候hang住了,结束掉,结局完事后,再次运行root.sh报错 WARNING: dir ...

  2. 【Oracle】生成随机数

    Oracle生成随机数: dbms_random.string(opt, 6)     --括号里的opt要从下面的列表中选择,数字代表要生成几位随机数,如果是1位的话,就改成1 以此类推 opt可取 ...

  3. PHP反序列化 - Pikachu

    概述 序列化serialize()序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{ public $test="pikachu"; } $s ...

  4. iptables自动屏蔽访问网站最频繁的IP

    iptables自动屏蔽访问网站频繁的IP 屏蔽每分钟访问超过200的IP 方法1:根据访问日志(Nginx为例 #!/bin/bash DATE=$(date +%d/%b/%Y:%H:%M) AB ...

  5. 【开源】我和 JAP(JA Plus) 的故事

    JA Plus 故事 程序员的故事如此简单之绕不过去的开源情结 我们准备做一件伟大的事,也可以说是一件真真正正普惠的事. 絮 是的,你没有看错,就是"絮"而非"序&quo ...

  6. Java运算符及包机制

    Java中的运算符及包机制 算术运算符:+ - * / % ++ -- 赋值运算符:=,+=,-=,*=,/= 关系运算符:>,<,>=,<=,==,!=,instanceof ...

  7. 找不到:DarchetypeCatalog=local

    设置IDEA Maven->Runner 界面的VM Options参数值为-DarchetypeCatalog=local 刷新项目Maven配置,在项目右边界面,重新引入Maven

  8. connection-backoff ConnectionBackoff Strategy 回退

    grpc/connection-backoff.md at master · grpc/grpc https://github.com/grpc/grpc/blob/master/doc/connec ...

  9. css知识补充

    盒子模型的介绍: 在网页中基本上都会显示一些方方正正的盒子,这种盒子就被我们称为盒模型 盒子模型的五个属性: width,height,border(边框),padding(内边距),margin(外 ...

  10. Webpack4.0各个击破(5)module篇

    一. 模块化乱炖 脚本合并是基于模块化规范的,javascript模块化是一个非常混乱的话题,各种[*MD]规范乱飞还要外加一堆[*.js]的规范实现.现代化前端项目多基于框架进行开发,较为流行的框架 ...