代码编译运行平台:Linux 64bits+g++(-m64),-m64表示生成64bits的程序。


在进行Linux网络编程时,经常用到本机IP地址。本文罗列一下常见方法,以备不时之需。

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

参考网络和书本,编程获取本机IP地址大约有以下几种方法。

方法一:ioctl()获取本地IP地址
Linux 下 可以使用ioctl()函数以及结构体 struct ifreq和结构体struct ifconf来获取网络接口的各种信息。

具体过程是先通过ictol获取本地的所有接口信息,存放到ifconf结构中,再从其中取出每个ifreq表示的ip信息(一般每个网卡对应一个IP地址,如:”eth0…、eth1…”)。

先了解结构体 struct ifreq和结构体struct ifconf:

//ifconf通常是用来保存所有接口信息的
//if.h
struct ifconf
{int    ifc_len;    /* size of buffer */union {char *ifcu_buf;  /*input from user->kernel*/struct ifreq *ifcu_req; /* return from kernel->user*/} ifc_ifcu;
};#define ifc_buf ifc_ifcu.ifcu_buf /*buffer address */
#define ifc_req ifc_ifcu.ifcu_req /*array of structures*///ifreq用来保存某个接口的信息
//if.h
struct ifreq {char ifr_name[IFNAMSIZ];union {struct sockaddr ifru_addr;struct sockaddr ifru_dstaddr;struct sockaddr ifru_broadaddr;short ifru_flags;int ifru_metric;caddr_t ifru_data;} ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_broadaddr ifr_ifru.ifru_broadaddr

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

string getLocalIP(){int inet_sock;  struct ifreq ifr;
char ip[32]={NULL};  inet_sock = socket(AF_INET, SOCK_DGRAM, 0);  strcpy(ifr.ifr_name, "eth0");  ioctl(inet_sock, SIOCGIFADDR, &ifr);  strcpy(ip, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));  return string(ip);
}

如果想获取所有网络接口信息,参见如下代码:

#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>#include <stdio.h>
#include <stdlib.h>int main(int argc,char* argv[])
{int sockfd;struct ifconf ifconf;struct ifreq *ifreq;char buf[512];//缓冲区//初始化ifconfifconf.ifc_len =512;ifconf.ifc_buf = buf;if ((sockfd =socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket" );exit(1);}ioctl(sockfd, SIOCGIFCONF, &ifconf); //获取所有接口信息//接下来一个一个的获取IP地址ifreq = (struct ifreq*)ifconf.ifc_buf;printf("ifconf.ifc_len:%d\n",ifconf.ifc_len);printf("sizeof (struct ifreq):%d\n",sizeof (struct ifreq));for (int i=(ifconf.ifc_len/sizeof (struct ifreq)); i>0; i--){if(ifreq->ifr_flags == AF_INET){ //for ipv4printf("name =[%s]\n" , ifreq->ifr_name);printf("local addr = [%s]\n" ,inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));ifreq++;}}getchar();//system("pause");//not used in linux return 0;
}

运行输出:

方法二:getsockname()获取本地IP地址
如果建立TCP连接的情况下,可以通过getsockname和getpeername函数来获取本地和对端的IP和端口号。前提是已经与对方建立了连接。
参考代码如下:

#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>int main(int argc, char* argv[])
{int fd=socket(AF_INET,SOCK_STREAM,0);//创建本地sock描述符struct sockaddr_in servaddr,localaddr,peeraddr;socklen_t len;//初始化服务端地址并连接bzero(&servaddr,sizeof(servaddr));servaddr.sin_family=AF_INET;servaddr.sin_port=htons(PORT);//PORT自己指定char* servIP=”177.56.23.4”;//服务端IPinet_pton(AF_INET,servIP,&servaddr.sin_addr);if(connect(fd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0){cerr<<"connect error"<<endl;return -1;}char buf[30]="";bzero(&localaddr,sizeof(localaddr));getsockname(fd,(struct sockaddr*)&localaddr,&len);  //获取本地信息cout<<"local ip is "<<inet_ntop(AF_INET,&localaddr.sin_addr,buf,sizeof(buf))<<"local port is"<<ntohs(localaddr.sin_port)<<endl; bzero(&peeraddr,sizeof(peeraddr));getpeername(fd,(struct sockaddr*)&peeraddr,&len);   //获取对端信息cout<<"peer ip is "<< inet_ntop(AF_INET,&peeraddr.sin_addr,buf,sizeof(buf))<<"peer port is "<<ntohs(peeraddr.sin_port)<<endl;return 1;
}
}

下面两种方法,都是通过主机名称来获取主机的IP地址,在获取本地IP地址时,一般都是回环地址,但可以有效的根据主机名称获取网络中的主机的IP地址,如通过域名获取域名对应的IP地址。

要想精确的获取某块网卡绑定的IP地址,请根据ioctl()和接口名称(如eth0)来获取,具体实现见上文。

方法三:getaddrinfo()获取本地IP地址
注意,getaddrinfo()可以完成网络主机中主机名和服务名到地址的映射,但是一般不能用来获取本地IP地址,当它用来获取本地IP地址时,返回的一般是127.0.0.1本地回环地址。
所需头文件:

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

用例如下:

#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>#include <stdio.h>
#include <stdlib.h>int main(int argc,char* argv[])
{char host_name[128]={NULL};gethostname(host_name, sizeof(host_name));//获取本地主机名称printf("host_name:%s\n",host_name);struct addrinfo *ailist=NULL,*aip=NULL;struct sockaddr_in *saddr;char *addr;int ret=getaddrinfo(host_name,NULL,NULL,&ailist);for(aip=ailist; aip!=NULL; aip=aip->ai_next){if(aip->ai_family==AF_INET){saddr=(struct sockaddr_in*)aip->ai_addr;addr=inet_ntoa(saddr->sin_addr);}printf("addr:%s\n",addr);}printf("\n-----------------baidu host info-------------------\n");getaddrinfo("www.baidu.com","http",NULL,&ailist);for(aip=ailist; aip!=NULL; aip=aip->ai_next){if(aip->ai_family==AF_INET){saddr=(struct sockaddr_in*)aip->ai_addr;addr=inet_ntoa(saddr->sin_addr);}printf("baidu addr:%s\n",addr);}getchar(); return 0;
}

使用gcc编译此程序会出现error: dereferencing pointer to incomplete type的错误,使用g++编译通过,程序输出:


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

string getLocalIP(char* local_ip) {// 获取本地IP时,一般都是127.0.0.1char host_name[128]="";struct hostent *host_ent;gethostname(host_name, sizeof(host_name));host_ent = gethostbyname(host_name);const char* first_ip = inet_ntoa(*(struct in_addr*)(host_ent->h_addr_list[0]));memcpy(local_ip, first_ip, 16);return string(host_name);
}

注意,主机的地址是一个列表的形式,原因是当一个主机有多个网络接口时,及多块网卡或者一个网卡绑定多个IP地址时,自然就有多个IP地址。以上代码获取的是根据主机名称得到的第一个IP地址。


参考文献
[1]http://blog.sina.com.cn/s/blog_9df3961501010hzj.html
[2]http://blog.csdn.net/darennet/article/details/9338819

Linux下编程获取本地IP地址的常见方法相关推荐

  1. 获取本地ip地址适用于windows和Linux环境

    简写版本 package com.gblfy.util;import java.net.Inet4Address; import java.net.InetAddress; import java.n ...

  2. android 获取wifi的ip地址吗,Android开发实现在Wifi下获取本地IP地址的方法

    本文实例讲述了Android开发实现在Wifi下获取本地IP地址的方法.分享给大家供大家参考,具体如下: 代码核心介绍: WifiManager类提供了对设备Wifi功能的管理,包括Wifi开关的打开 ...

  3. //获取本地IP地址和对端IP地址

    1 //获取本地IP地址 2 CHAR * GetLocalIpAdrr(int fd) 3 { 4 struct sockaddr_in stHost; 5 memset(&stHost, ...

  4. vue中获取本地IP地址

    vue中获取本地IP地址 IP地址需要通过js获取: 网上有很多查询接口可以获取到IP,查到的搜狐的比较多,我这里就用搜狐的: http://pv.sohu.com/cityjson?ie=utf-8 ...

  5. 通过js获取本地IP地址

    通过js获取本地IP地址 最近在做pc项目,需要根据用户的IP地址定位城市.IP地址需要通过js获取: 网上有很多查询接口可以获取到IP,我这里用的是搜狐的: http://pv.sohu.com/c ...

  6. Linux下查看DNS服务器IP地址以及使用host命令查询域名对应的IP地址

    Linux下查看DNS服务器IP地址以及使用host命令查询域名对应的IP地址 Linux使用etc/resolv.conf文件来存放DNS服务器的IP地址,使用cat命令查看. cat /etc/r ...

  7. VC 获取本地ip地址

    获取本地IP地址有两种做法.一种是使用gethostname函数,代码如下: [cpp] view plaincopy bool CSocketComm::GetLocalAddress(std::s ...

  8. android 获取设备的mac地址,Android编程获取设备MAC地址的实现方法

    本文实例讲述了Android编程获取设备MAC地址的实现方法.分享给大家供大家参考,具体如下: /** * 获取设备的mac地址 * * @param ac * @param callback * 成 ...

  9. 关于java获取本地ip的几种方法

    关于java获取本地ip的几种方法 1.获取本地ip的方法 System.out.println(InetAddress.getLocalHost().getHostAddress()); 2.域名解 ...

最新文章

  1. 7000p可以加装固态吗_解惑丨地暖不热加装循环泵可以吗?
  2. JspServlet之Cookie
  3. Windows Server 2008 R2之管理Sysvol文件夹
  4. 电话号码的字母组合—leetcode17
  5. EF Code First 学习笔记:关系(转)
  6. 434. 字符串中的单词数
  7. 【Python基础知识-pycharm版】第二节-赋值/数据类型/时间点/运算符/字符串
  8. ignite mysql_redis、ignite、mysql memory 内存数据库性能测试对比
  9. php mysql 框架 php5.2_简单快速安装Apache+PHP+MySql服务环境(四)—— 将php版本升级到7.2...
  10. 速度更新!GoCD又曝仨洞,极易遭利用且结合利用可成供应链攻击的新跳板
  11. 在进行了解JAVA CLASS文件解析时必须要明白的三个概念
  12. php 合计,表格怎么合计总数
  13. 计算机应用高级工程师,高级工程师职称考试项目
  14. sh: arithmetic expression: expecting primary
  15. java xtend_Eclipse Xtend对Java说:我帮你瘦身
  16. 我们该如何高效的学习
  17. 斯皮格尔:我们敢于采纳非常疯狂的创意
  18. 微信小程序体验版ios白屏 安卓报错 {“errMsg“:“hideLoading:fail:toast can‘t be found“}
  19. 计算机多媒体应用技术ppt课件ppt,ppt课件-计算机多媒体技术.ppt
  20. Android搭建WebSocket服务端

热门文章

  1. Jenkins 文档特别兴趣小组
  2. 如何实现用户认证授权系统
  3. 用Python写一个简单的监控系统
  4. 别以为真懂Openstack: 虚拟机创建的50个步骤和100个知识点(1)
  5. 免费的响应式bootstrap管理员后台界面主题 - Charisma
  6. linux 临时文件 清理,Linux临时文件的清理
  7. 蓝桥杯 ALGO-55 算法训练 矩阵加法
  8. iOS模拟器中修改textField键盘类型为中文输入和键盘弹出方法
  9. printf打印数组_(45)C++面试之把数组排成最小的数
  10. 前后分离架构下跨域调试