struct ifreq結構體與ip,子網掩碼,網關等信息


總結一下,今天學習的關於通過socket,ioctl來獲得ip,netmask等信息,其中很多內容參照了很多網上的信息,我會一一列出的

我用的這個函數,就是下面這個函數,其中的有一些全局變量,很好懂,也就不多做解釋了
一。下面對這個函數進行注解一下:

int get_nic_IP_Address()//獲取各網卡IP地址、子網掩碼
{
 struct ifreq ifreq;  //聲明一個struct ifreq結構體(這個結構體中有很多重要的參數,具體可以參照第二的補充)
   int sock;
 int i;
 int tmpint;
 read_dev(); //這個函數的功能是獲得網卡名字(保存在下面提到的sys_nic_ip[][]數組中)並計算網卡總數(就是下面的sys_nic_count)

 for (i=0;i<sys_nic_count;i++)
 {
     if((sock=socket(AF_INET,SOCK_STREAM,0))<0){  //建立一個套接字
         perror("socket");
         return ;
        }
     strcpy(ifreq.ifr_name,sys_nic_name[i]);   //把網卡名字復制到ifreq結構體中的name變量(感覺這個地方是必須的)
     if(ioctl(sock,SIOCGIFADDR,&ifreq)<0) {   //這里涉及ioctl函數對於網絡文件的控制(下面會介紹)
       sprintf(sys_nic_ip[i],"Not set");
     } else {
       sprintf(sys_nic_ip[i],"%d.%d.%d.%d",      //把ip地址提取出來,保存(理解一下socketaddr_in和socketaddr的關系)
       (unsigned char)ifreq.ifr_addr.sa_data[2],
       (unsigned char)ifreq.ifr_addr.sa_data[3],
       (unsigned char)ifreq.ifr_addr.sa_data[4],
       (unsigned char)ifreq.ifr_addr.sa_data[5]);
     }
     if(ioctl(sock,SIOCGIFNETMASK,&ifreq)<0) {  //我的理解是這個地方用SIOCGIFNETMASK,那么ifreq中原本是存的ip地址,現在存成了子網掩碼了。。
       sprintf(sys_nic_mask[i],"Not set");       //把子網掩碼提取出來(但得到的只是超網的划分方式就是/xx)
     } else {
       sprintf(sys_nic_mask[i],"%d",
       Count((unsigned char)ifreq.ifr_netmask.sa_data[2])+
       Count((unsigned char)ifreq.ifr_netmask.sa_data[3])+
       Count((unsigned char)ifreq.ifr_netmask.sa_data[4])+
       Count((unsigned char)ifreq.ifr_netmask.sa_data[5]));
       
     }
 }
}
列出上面最后調用函數(Count())和一些全副變量:
char sys_nic_ip[20][20];//各網卡IP
char sys_nic_mask[20][20];//各網卡子網掩碼"/xx"

int countTable[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
int Count(int v)

  return countTable[v]; 
}
應該理解了吧。。。挺經典的。。。不過網上的貌似就有一個版本。。。很是氣惱

二。對涉及的知識點進行補充

1.struct ifreq {
    char ifr_name[IFNAMSIZ];
     union
      {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        struct sockaddr ifru_netmask;
        struct sockaddr ifru_hwaddr;
        short int ifru_flags;
        int ifru_ivalue;
        int ifru_mtu;
        struct ifmap ifru_map;
        char ifru_slave[IFNAMSIZ]; /* Just fits the size */
        char ifru_newname[IFNAMSIZ];
        __caddr_t ifru_data;
      } ifr_ifru;
};

# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_map ifr_ifru.ifru_map /* device map */
# define ifr_slave ifr_ifru.ifru_slave /* slave device */
# define ifr_data ifr_ifru.ifru_data /* for use by interface */
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define ifr_newname ifr_ifru.ifru_newname /* New name */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)


2.ioctl 函數 (在網絡中的作用)
關於這個網絡相關的請求,就是ioctl在這里面起的作用和各個參數的作用。。。可以參照這個網頁,講解的很詳細:
http://www.iteye.com/topic/309442
本例中用的2個ioctl控制函數。。上面已經解釋很清楚了

3.關於socketaddr_in和socketaddr的關系,下面貼出具體的定義:
struct sockaddr_in 

short int sin_family; /* 地址族 */ 
unsigned short int sin_port; /* 端口號 */ 
struct in_addr sin_addr; /* IP地址 */ 
unsigned char sin_zero[8]; /* 填充0 以保持與struct sockaddr同樣大小 */ 
};

struct sockaddr 

unsigned short sa_family; /* 地址族, AF_xxx */ 
char sa_data[14]; /* 14 字節的協議地址 */ 
};

比較一下,會發現長度一樣,所以這2個可以通用的,不過要進行類型轉換,比較一下就得出了為什么上面程序中可以用:
(unsigned char)ifreq.ifr_addr.sa_data[2],這種形式了,還是解釋一下吧:這個ifr_addr是一個struct sockaddr結構體。它其中的sa_date[2]是不是照着上面sockaddr_in中的sin_add(也就是ip地址呢),該明白了吧。。。。

總結:通過這個函數,可以很好的理解怎么得到ip和子網掩碼的過程。。。。


免責聲明!

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



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