http://blog.csdn.net/windeal3203/article/details/39320605
Linux 下 可以使用ioctl()函數 以及 結構體 struct ifreq ?結構體struct ifconf來獲取網絡接口的各種信息。
ioctl
首先看ioctl()用法
ioctl()原型如下:
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...);
參數:
? ??fd ? ? : 文件描述符
request: ?表示要請求的信息。如IP地址、網絡掩碼等
? ???...? ???:??后面的可變參數根據request而定
比如我們請求所有網絡接口的清單:
- struct?ifconf?IoCtlReq;??
- ...??
- ioctl(?Sock,?SIOCGIFCONF,?&IoCtlReq?)??
其中IoCtlReq 是一個
與接口相關的request如下表所示(來源:?<http://baike.baidu.com/view/1081282.htm?fr=aladdin>):
接 口 | SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFFLAGS SIOCGIFFLAGS SIOCSIFDSTADDR SIOCGIFDSTADDR SIOCGIFBRDADDR SIOCSIFBRDADDR SIOCGIFNETMASK SIOCSIFNETMASK SIOCGIFMETRIC SIOCSIFMETRIC SIOCGIFMTU SIOCxxx | 獲取所有接口的清單 設置接口地址 獲取接口地址 設置接口標志 獲取接口標志 設置點到點地址 獲取點到點地址 獲取廣播地址 設置廣播地址 獲取子網掩碼 設置子網掩碼 獲取接口的測度 設置接口的測度 獲取接口MTU (還有很多取決于系統的實現) | struct ifconf struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq struct ifreq |
關于ioctl的詳細解釋清查閱本博其它博文
結構體 struct ifreq用來保存某個接口的信息。
- ??
- ?
- ?
- ?
- ?
- ?
- ??
- struct?ifreq?{??
- #define?IFHWADDRLEN?6??
- ????union??
- ????{??
- ????????char????ifrn_name[IFNAMSIZ];??????????
- ????}?ifr_ifrn;??
- ??????
- ????union?{??
- ????????struct??sockaddr?ifru_addr;??
- ????????struct??sockaddr?ifru_dstaddr;??
- ????????struct??sockaddr?ifru_broadaddr;??
- ????????struct??sockaddr?ifru_netmask;??
- ????????struct??sockaddr?ifru_hwaddr;??
- ????????short???ifru_flags;??
- ????????int?ifru_ivalue;??
- ????????int?ifru_mtu;??
- ????????struct??ifmap?ifru_map;??
- ????????char????ifru_slave[IFNAMSIZ];?????
- ????????char????ifru_newname[IFNAMSIZ];??
- ????????void?__user?*???ifru_data;??
- ????????struct??if_settings?ifru_settings;??
- ????}?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?ifr_settings????ifr_ifru.ifru_settings??/*?Device/proto?settings*/??
ifr_name 標識了某一接口。
可以通過ioctl獲取該接口的信息。如:
ioctl(Sock, SIOCGIFNETMASK, &IfReq);//獲取網絡接口地址掩碼
該代碼需要先對IfReq->ifr_name賦值,然后獲取與IfReq->ifr_name向匹配的網絡接口 的地址掩碼
struct ifconf
結構體struct ifconf通常用來保存所有接口信息
- ??
- ?
- ?
- ?
- ?
- ?
- ??
- struct?ifconf??{??
- ????int?ifc_len;??????????????
- ????union?{??
- ????????char?__user?*ifcu_buf;??
- ????????struct?ifreq?__user?*ifcu_req;??
- ????}?ifc_ifcu;??
- };??
- #define?ifc_buf?ifc_ifcu.ifcu_buf???????/*?buffer?address???*/??
- #define?ifc_req?ifc_ifcu.ifcu_req???????/*?array?of?structures??*/??
該結構體可以用來獲取所喲網絡接口的名字和信息(不是全部信息,是ip地址)
(圖片來自:http://tech.sunplusedu.com/space/post-4064.aspx)
Example:
- #include?<sys/types.h>????
- #include?<sys/ioctl.h>????
- #include?<sys/socket.h>????
- #include?<net/if.h>????
- #include?<stdio.h>????
- #include?<stdlib.h>????
- #include?<unistd.h>????
- #include?<netdb.h>????
- #include?<string.h>????
- #include?<fcntl.h>????
- #include?<string.h>????
- #include?<errno.h>??
- typedef?uint32_t?uint32;???
- #define?MAX_IF?10??
- int???
- main()??
- {??
- ????struct?ifreq?ifVec[MAX_IF];??
- ??????
- ????int?sock?=?-1;??
- ????if?(?(sock?=?socket(?AF_INET,?SOCK_DGRAM,?0?))?<?0?)??
- ????????fprintf(stderr,?"Error:%d,?cannot?open?RAM;\n");??
- ??????
- ??????
- ????struct?ifconf?ioIfConf;??
- ????????ioIfConf.ifc_buf?=?(void?*)ifVec;??
- ????????ioIfConf.ifc_len?=?sizeof(ifVec);??
- ?????printf("Len:%d\n",?ioIfConf.ifc_len);???????
- ??????????
- ????if?(ioctl(sock,?SIOCGIFCONF,?&ioIfConf)?<?0?)??
- ????????fprintf(stderr,?"Error:%d???ioctl?IFCONF\n");??
- ??????
- ?????printf("Len:%d\n",?ioIfConf.ifc_len);??
- ??????
- ????{??
- ????????struct?ifreq?*ifPt;??
- ????????struct?ifreq?*ifEndPt;??
- ????????ifPt?=?ifVec;??
- ????????ifEndPt?=?(void?*)((char?*)ifVec?+?ioIfConf.ifc_len);??
- ????????for?(ifPt?=?ifVec;?ifPt?<?ifEndPt;?ifPt++)??
- ????????{??
- ????????????struct?ifreq?ifReq;??
- ????????????if?(?ifPt->ifr_addr.sa_family?!=?AF_INET?)?{??
- ????????????????????????continue;??
- ????????????????????}??
- ??????????????
- ??????????????
- ????????????uint32?u32_addr,?u32_mask;??
- ??????????????
- ??????????????
- ????????????char?ipDotBuf[16],?subnetDotBuf[16],?maskDotBuf[16];???
- ????????????u32_addr?=?((struct?sockaddr_in?*)&ifPt->ifr_addr)->sin_addr.s_addr;??
- ????????????inet_ntop(AF_INET,?&u32_addr,?ipDotBuf,?(socklen_t?)sizeof(ipDotBuf));???
- ????????????printf("IP?Address:?%s\n",?ipDotBuf);??
- ??????????????
- ??????????????
- ????????????bzero(&ifReq,sizeof(struct?ifreq));????
- ????????????memcpy(ifReq.ifr_name,?ifPt->ifr_name,?sizeof(ifReq.ifr_name));????
- ????????????if?(ioctl(sock,?SIOCGIFNETMASK,?&ifReq?)?<?0){??
- ????????????????fprintf(stderr,?"Error:?%d,?cannot?get?mask\n",?errno);??
- ????????????}??
- ????????????else{??
- ????????????????u32_mask?=?((struct?sockaddr_in?*)&ifReq.ifr_addr)->sin_addr.s_addr;??
- ????????????????inet_ntop(AF_INET,?&u32_mask,?maskDotBuf,?(socklen_t?)sizeof(maskDotBuf));??
- ????????????????printf("Mask:?%s\n",?maskDotBuf);??
- ????????????}?????
- ??????????????
- ????????????bzero(&ifReq,sizeof(struct?ifreq));????
- ????????????memcpy(ifReq.ifr_name,?ifPt->ifr_name,?sizeof(ifReq.ifr_name));????
- ????????????if?(ioctl(sock,?SIOCGIFMTU,?&ifReq?)?<?0){??
- ????????????????fprintf(stderr,?"Error:?%d,?cannot?get?MTU\n",?errno);??
- ????????????}??
- ????????????else{??
- ????????????????printf("SIOCGIFMTU:%d\n",?ifReq.ifr_mtu);???
- ????????????}??
- ?????????????????
- ????????}??
- ????}??
- ??????
- ??????
- ??????
- }??
運行結果:
- windeal@ubuntu:~/Windeal/apue$?./exe???
- Len:320??
- Len:64??
- IP?Address:?127.0.0.1??
- Mask:?255.0.0.0??
- SIOCGIFMTU:16436??
- IP?Address:?172.17.92.198??
- Mask:?255.255.254.0??
- SIOCGIFMTU:1500??
- windeal@ubuntu:~/Windeal/apue$???