实习笔记(九)——获取本地IP

在Linux下获取本地IP跟WINDOS下不一样,我先是在windows下编程的,测试过下面这个获取IP的函数是可用的:

 

VOID CRTSPServer::GetLocalIP(CHAR *localip)
{
   CHAR caHostName[20];
   CHAR caTty[10];
   INT namelen=16;

   CHAR *tmp;
  
   struct hostent *h;

   struct in_addr addr;
   memset(caHostName,0x00,sizeof(caHostName));
   memset(caTty,0x00,sizeof(caTty));
   gethostname(caHostName, namelen);
   if ((h=gethostbyname(caHostName)) == NULL)
   {
    localip = NULL;
   }

    memcpy(&addr, h->h_addr_list[0], sizeof(struct in_addr));

   tmp=inet_ntoa(addr);

   strcpy(localip,tmp);
   
   localip[strlen(tmp)]='/0';

   return ;
}

 

可是,移植到Linux下之后,就不是得到本地IP了,而是一个奇怪的IP格式的值。后来网上查LINUX下的获取IP的方法,下面这段代码是到处都在引用的,但是却得不到正确的IP地址。

 

string s = getlocalip("eth0"); 

  1. static string getlocalip(const string& eth)  
  2.         {  
  3.             int sockfd;  
  4.             if(-1 == (sockfd = socket(PF_INET, SOCK_STREAM, 0)))  
  5.             {  
  6.                 return "";  
  7.             }  
  8.             char ipbuf[16];  
  9.             struct ifreq req;  
  10.             struct sockaddr_in *host;  
  11.             bzero(&req, sizeof(struct ifreq));  
  12.             strcpy(req.ifr_name, eth.c_str());  
  13.             ioctl(sockfd, SIOCGIFADDR, &req);  
  14.             host = (struct sockaddr_in*)&req.ifr_addr;  
  15.             strcpy(ipbuf, inet_ntoa(host->sin_addr));  
  16.             close(sockfd);  
  17.             string r = string(ipbuf);  
  18.             return r;  
  19. }  

似乎这是用一系列的网络函数弄出来的,如无意外,我的虚拟机不是用"eth0"这一地址。

 

最后,在网上找到了以下的介绍,学习了。

 

源代码级Unix/Linux 通用网卡IP地址获取方法

在Unix和Linux系统下有两种方法可以获得系统IP地址 (gethostbyname和ioctl)

gethostbyname通过域名解析获取对应计算机的网络地址,ioctl是一系列的网络函数获得本机的IP

(推荐使用ioctl方法,这个方法能给出的ip 与ifconfig命令显示的ip一致,并且能不经修改的在arm板上正常运行。
而gethostname() 联合gethostbyname()方法给出的ip与ifconfig给出的并不一致,无法使用[还不懂为什么],并且在arm板上不能正确运行。)

ioctl范例程序
#include <stdio.h>
#include <sys/types.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>


int main(void)
{
       int s;
       struct ifconf conf;
       struct ifreq *ifr;
       char buff[BUFSIZ];
       int num;
       int i;

       s = socket(PF_INET, SOCK_DGRAM, 0);
       conf.ifc_len = BUFSIZ;
       conf.ifc_buf = buff;

       ioctl(s, SIOCGIFCONF, &conf);
       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);

               ioctl(s, SIOCGIFFLAGS, ifr);
               if(((ifr->ifr_flags & IFF_LOOPBACK) == 0) && (ifr->ifr_flags & IFF_UP))
               {
                       printf("%s (%s)/n",
                               ifr->ifr_name,
                               inet_ntoa(sin->sin_addr));
               }
               ifr++;
       }
}

输出:
eth1 (10.60.68.127)
第二种方法:(不推荐,虽然代码稍微简单,有效运行场合尚未明确)

 

主要通过这两个函数:gethostname()和gethostbyname()

 

int gethostname(char *name, size_t namelen);

DESCRIPTION

The gethostname() function shall return the standard host name for the current machine. The namelen argument shall specify the size of the array pointed to by the name argument. The returned name shall be null-terminated, except that if namelen is an insufficient length to hold the host name, then the returned name shall be truncated and it is unspecified whether the returned name is null-terminated.

Host names are limited to {HOST_NAME_MAX} bytes.

struct hostent *gethostbyname(const char *name);
这个函数的传入值是域名或者主机名,例如"
www.google.com","wpc" 等等。
传出值,是一个hostent的结构(如下)。如果函数调用失败,将返回NULL。

struct hostent {
  char  *h_name;
  char  **h_aliases;
  int   h_addrtype;
  int   h_length;
  char  **h_addr_list;
  };
解释一下这个结构:
其中,
  char *h_name 表示的是主机的规范名。例如
www.google.com的规范名其实是www.l.google.com
  char   **h_aliases 表示的是主机的别名。
www.google.com就是google他自己的别名。有的时候,有的主机可能有好几个别名,这些,其实都是为了易于用户记忆而为自己的网站多取的名字。
  int   h_addrtype 表示的是主机ip地址的类型,到底是ipv4(AF_INET),还是ipv6(AF_INET6)
  int   h_length 表示的是主机ip地址的长度
  int   **h_addr_lisst 表示的是主机的ip地址,注意,这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西,会有问题的哇。所以到真正需要打印出这个 IP的话,需要调用inet_ntop()。

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) :
这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。
这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。

 

下面是例程,有详细的注释。

#include <stdio.h>
#include <arpa/inet.h>  //for inet_ntop()

#include <unistd.h>  //for gethostname()
#include <netdb.h>       //for gethostbyname()
#include <sys/socket.h>

int main(int argc, char **argv)
{
 char **pptr;
 struct hostent *hptr;
 char hostname[32];
 char str[32];
 
 if(gethostname(hostname,sizeof(hostname)) )
 {
  printf("gethostname calling error/n");
  return 1;
 }
 /* 调用gethostbyname()。调用结果都存在hptr中 */
 if( (hptr = gethostbyname(hostname) ) == NULL )
 {
  printf("gethostbyname error for host:%s/n", hostname);
  return 0; /* 如果调用gethostbyname发生错误,返回1 */
 }
 /* 将主机的规范名打出来 */
 printf("official hostname:%s/n",hptr->h_name);
 /* 主机可能有多个别名,将所有别名分别打出来 */
 for(pptr = hptr->h_aliases; *pptr != NULL; pptr++)
  printf("  alias:%s/n",*pptr);
 /* 根据地址类型,将地址打出来 */
 switch(hptr->h_addrtype)
 {
  case AF_INET:
  case AF_INET6:
   pptr=hptr->h_addr_list;
   /* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */
   for(;*pptr!=NULL;pptr++)
    printf("  address:%s/n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
   break;
  default:
   printf("unknown address type/n");
   break;
 }
 return 0;
}

运行输出结果:

official hostname:localhost.localdomain
  alias:localhost
  address:127.0.0.1

(给出的这个ip好像没什么意义,在另外一台机器上运行,给出ip是:192.168.0.3,而ifconfig给出的ip是 192.168.2.100,这是怎么回事?虽然电脑都有双网卡)

 

参考来自:

http://blog.chinaunix.net/u1/44472/showart_350753.html

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值