c++ 獲取本地ip地址


 
         
最終版本:采用指針傳參數,不使用別名形式。
#include <unistd.h>
#include <netdb.h>  //gethostbyname
#include <arpa/inet.h>  //ntohl
#include <iostream>
using namespace std;

int get_local_ip(int *ip) {
    char hostname[128];
    int ret = gethostname(hostname, sizeof(hostname));
    if (ret == -1){
        return -1;
    }
    struct hostent *hent;
    hent = gethostbyname(hostname);
    if (NULL == hent) {
        return -1;
    }
    //直接取h_addr_list列表中的第一個地址h_addr
    *ip = ntohl(((struct in_addr*)hent->h_addr)->s_addr);
    //int i;
    //for(i=0; hent->h_addr_list[i]; i++) {
    //    uint32_t u = ntohl(((struct in_addr*)hent->h_addr_list[i])->s_addr);
    //    std::cout << u << std::endl;
    //}
    return 0;
}

int main() {


    //10.94.45.25 
    //unsigned long ii = 0l;

    //ii |= 25;
    //ii |= 45 << 8;
    //ii |= 94 << 16;
    //ii |= 10 << 24;

    //cout << ii << endl;





    int ip = 0;
    int ret = get_local_ip(&ip);
    if (ret == 0) {
        cout << ip << endl;
    } else {
        cerr << "wrong" << endl;
    }
    return 0;
}


/* vim: set ts=4 sw=4 sts=4 tw=100 */

 




/*最終定稿*/

#include <unistd.h> #include <netdb.h> //gethostbyname #include <arpa/inet.h> //ntohl #include <iostream> using namespace std; int get_local_ip(int& ip) { char hostname[128]; int ret = gethostname(hostname, sizeof(hostname)); if (ret == -1){ return -1; } struct hostent *hent; hent = gethostbyname(hostname); if (NULL == hent) { return -1; } //直接取h_addr_list列表中的第一個地址h_addr ip = ntohl(((struct in_addr*)hent->h_addr)->s_addr); //int i; //for(i=0; hent->h_addr_list[i]; i++) { // uint32_t u = ntohl(((struct in_addr*)hent->h_addr_list[i])->s_addr); // std::cout << u << std::endl; //} return 0; } int main() { //10.94.45.25 //unsigned long ii = 0l; //ii |= 25; //ii |= 45 << 8; //ii |= 94 << 16; //ii |= 10 << 24; //cout << ii << endl; int ip; int ret = get_local_ip(ip); if (ret == 0) { cout << ip << endl; } else { cerr << "wrong" << endl; } return 0; }
 
         

 



c ip地址知識點:

 struct   sockaddr   {  
                unsigned   short   sa_family;     
                char   sa_data[14];     

        };  
sockaddr_in詳解
sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET,代表地址組

sa_data是14字節協議地址。

sockaddr 是通用的socket地址,具體到Internet   socket,用下面的結構,二者可以進行類型轉換  

  struct   sockaddr_in   {  
                short   int   sin_family;     // Address family 一般來說 AF_INET(地址族)PF_INET(協議族 )
                unsigned   short   int   sin_port;  //sin_port存儲端口號(使用網絡字節順序),在linux下,端口號的范圍0~65535,同時0~1024范圍的端口號已經被系統使用或保留
                struct   in_addr   sin_addr;     //存儲IP地址
                unsigned   char   sin_zero[8];  //sin_zero是為了讓sockaddr與sockaddr_in兩個數據結構保持大小相同而保留的空字節   
        };  
        struct   in_addr就是32位IP地址。  
        struct   in_addr   {  
                union {
                        struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
                        struct { u_short s_w1,s_w2; } S_un_w;
                        u_long S_addr; //s_addr按照網絡字節順序存儲IP地址
                } S_un;

                #define s_addr  S_un.S_addr
        };   
 
         

 

 
在C/C++寫網絡程序的時候,往往會遇到字節的網絡順序和主機順序的問題。這是就可能用到htons(), ntohl(), ntohs(),htons()這4個函數。
網絡字節順序與本地字節順序之間的轉換函數:
#include <arpa/inet.h>
htonl()--"Host to Network Long"
ntohl()--"Network to Host Long"
htons()--"Host to Network Short"
ntohs()--"Network to Host Short"

之所以需要這些函數是因為計算機數據表示存在兩種字節順序:NBO與HBO

網絡字節順序NBO(Network Byte Order): 按從高到低的順序存儲,在網絡上使用統一的網絡字節順序,可以避免兼容性問題。

主機字節順序(HBO,Host Byte Order): 不同的機器HBO不相同,與CPU設計有關,數據的順序是由cpu決定的,而與操作系統無關。
如 Intel x86結構下, short型數0x1234表示為34 12, int型數0x12345678表示為78 56 34 12  
如 IBM power PC結構下, short型數0x1234表示為12 34, int型數0x12345678表示為12 34 56 78
   
由於這個原因不同體系結構的機器之間無法通信,所以要轉換成一種約定的數序,也就是網絡字節順序,其實就是如同power pc那樣的順序. 
在PC開發中有ntohl和htonl函數可以用來進行網絡字節和主機字節的轉換.
這個數據結構是這樣的: 
   struct hostent { 
   char *h_name; 
   char **h_aliases; 
   int h_addrtype; 
   int h_length; 
   char **h_addr_list; 
   }; 
   #define h_addr h_addr_list[0]  
這里是這個數據結構的詳細資料:  
struct hostent:  
  h_name – 地址的正式名稱。 
  h_aliases – 空字節-地址的預備名稱的指針。 
  h_addrtype –地址類型; 通常是AF_INET。  
  h_length – 地址的比特長度。 
  h_addr_list – 零字節-主機網絡地址指針。網絡字節順序。 
  h_addr - h_addr_list中的第一地址。 
gethostbyname() 成功時返回一個指向結構體 hostent 的指針,或者 是個空 (NULL) 指針。(但是和以前不同,不設置errno,h_errno 設置錯 誤信息。請看下面的 herror()。) 但是如何使用呢? 這個函數可不象它看上去那么難用。 
這里是個例子: 
#include <stdio.h> 
  #include <stdlib.h> 
  #include <errno.h> 
  #include <netdb.h> 
  #include <sys/types.h> 
  #include <netinet/in.h> 
int main(int argc, char *argv[]) 
   { 
   struct hostent *h; 
if (argc != 2) { /* 檢查命令行 */ 
   fprintf(stderr,"usage: getip address\n"); 
   exit(1); 
   } 
if ((h=gethostbyname(argv[1])) == NULL) { /* 取得地址信息 */ 
   herror("gethostbyname"); 
   exit(1); 
   } 
printf("Host name : %s\n", h->h_name); 
  printf("IP Address : %s\n",inet_ntoa(*((struct in_addr *)h->h_addr))); 
return 0; 
   } 
在使用 gethostbyname() 的時候,你不能用perror() 打印錯誤信息 (因為 errno 沒有使用),你應該調用 herror()。
相當簡單,你只是傳遞一個保存機器名的字符串(例如 "whitehouse.gov") 給gethostbyname(),然后從返回的數據結構 

struct hostent 中獲取信息。 唯一也許讓人不解的是輸出 IP 地址信息。h->h_addr 是一個 char *,
但是 inet_ntoa() 需要的是 struct in_addr。因此,我轉換 h->h_addr 成 struct in_addr *,然后得到數據。

 

 
         

 


============================================================
參考地址:http://blog.csdn.net/liuqinstudy/article/details/8813932
#include
<stdio.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <unistd.h> #include <sys/types.h> #include <netdb.h> #include <net/if.h> #include <arpa/inet.h> #include <iostream> using namespace std; int get_local_ip(unsigned long& ip) { int sfd, intr; struct ifreq buf[16]; struct ifconf ifc; sfd = socket(AF_INET, SOCK_DGRAM, 0); if (sfd < 0) return -1; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = (caddr_t)buf; if (ioctl(sfd, SIOCGIFCONF, (char *)&ifc)) return -1; intr = ifc.ifc_len / sizeof(struct ifreq); while (intr-- > 0 && ioctl(sfd, SIOCGIFADDR, (char *)&buf[intr])); close(sfd); ip = ntohl(((struct sockaddr_in*)(&buf[intr].ifr_addr))->sin_addr.s_addr); return 0; } int main() { unsigned long ip = 0; int ret = get_local_ip(ip); if (ret == 0) { cout << ip << endl; } else { cout << "err" << endl; } return 0; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM