Linux编程获取网络信息总结
生活随笔
收集整理的這篇文章主要介紹了
Linux编程获取网络信息总结
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Linux下C獲取所有可用網(wǎng)卡信息
在Linux下開(kāi)發(fā)網(wǎng)絡(luò)程序時(shí),經(jīng)常會(huì)遇到需要取本地網(wǎng)絡(luò)接口名、IP、廣播地址
、子網(wǎng)掩碼或者M(jìn)AC地址等信息的需求,最常見(jiàn)的辦法是配合宏SIOCGIFHWADDR、
SIOCGIFADDR、SIOCGIFBRDADDR與SIOCGIFNETMASK作為參數(shù)調(diào)用
在Linux下開(kāi)發(fā)網(wǎng)絡(luò)程序時(shí),經(jīng)常會(huì)遇到需要取本地網(wǎng)絡(luò)接口名、IP、廣播地址
、子網(wǎng)掩碼或者M(jìn)AC地址等信息的需求,最常見(jiàn)的辦法是配合宏SIOCGIFHWADDR、
SIOCGIFADDR、SIOCGIFBRDADDR與SIOCGIFNETMASK作為參數(shù)調(diào)用函數(shù)ioctl分別獲
得MAC地址、IP地址、廣播地址與子網(wǎng)掩碼來(lái)實(shí)現(xiàn)。一次性獲取此類信息的C語(yǔ)言
代碼實(shí)現(xiàn)如下。?
海姹網(wǎng)(網(wǎng)址:http://www.seacha.com),標(biāo)簽:Linux下C獲取所有可用網(wǎng)卡信
息, 網(wǎng)卡,ioctl,IP
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <errno.h>
int getLocalInfo(void)
{
? ? int fd;
? ? int interfaceNum = 0;
? ? struct ifreq buf[16];
? ? struct ifconf ifc;
? ? struct ifreq ifrcopy;
? ? char mac[16] = {0};
? ? char ip[32] = {0};
? ? char broadAddr[32] = {0};
? ? char subnetMask[32] = {0};
? ? if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
? ? {
? ? ? ? perror("socket");
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
? ? ifc.ifc_len = sizeof(buf);
? ? ifc.ifc_buf = (caddr_t)buf;
? ? if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc))
? ? {
? ? ? ? interfaceNum = ifc.ifc_len / sizeof(struct ifreq);
? ? ? ? printf("interface num = %dn", interfaceNum);
? ? ? ? while (interfaceNum-- > 0)
? ? ? ? {
? ? ? ? ? ? printf("ndevice name: %sn", buf[interfaceNum].ifr_name);
? ? ? ? ? ? //ignore the interface that not up or not runing ?
? ? ? ? ? ? ifrcopy = buf[interfaceNum];
? ? ? ? ? ? if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno),?
__FILE__, __LINE__);
? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? return -1;
? ? ? ? ? ? }
? ? ? ? ? ? //get the mac of this interface ?
? ? ? ? ? ? if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf
[interfaceNum])))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? memset(mac, 0, sizeof(mac));
? ? ? ? ? ? ? ? snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[0],
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[1],
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[2],
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[3],
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[4],
? ? ? ? ? ? ? ? ? ? (unsigned char)buf
[interfaceNum].ifr_hwaddr.sa_data[5]);
? ? ? ? ? ? ? ? printf("device mac: %sn", mac);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno),?
__FILE__, __LINE__);
? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? return -1;
? ? ? ? ? ? }
? ? ? ? ? ? //get the IP of this interface ?
? ? ? ? ? ? if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum]))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? snprintf(ip, sizeof(ip), "%s",
? ? ? ? ? ? ? ? ? ? (char *)inet_ntoa(((struct sockaddr_in *)&(buf
[interfaceNum].ifr_addr))->sin_addr));
? ? ? ? ? ? ? ? printf("device ip: %sn", ip);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno),?
__FILE__, __LINE__);
? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? return -1;
? ? ? ? ? ? }
? ? ? ? ? ? //get the broad address of this interface ?
? ? ? ? ? ? if (!ioctl(fd, SIOCGIFBRDADDR, &buf[interfaceNum]))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? snprintf(broadAddr, sizeof(broadAddr), "%s",
? ? ? ? ? ? ? ? ? ? (char *)inet_ntoa(((struct sockaddr_in *)&(buf
[interfaceNum].ifr_broadaddr))->sin_addr));
? ? ? ? ? ? ? ? printf("device broadAddr: %sn", broadAddr);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno),?
__FILE__, __LINE__);
? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? return -1;
? ? ? ? ? ? }
? ? ? ? ? ? //get the subnet mask of this interface ?
? ? ? ? ? ? if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum]))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? snprintf(subnetMask, sizeof(subnetMask), "%s",
? ? ? ? ? ? ? ? ? ? (char *)inet_ntoa(((struct sockaddr_in *)&(buf
[interfaceNum].ifr_netmask))->sin_addr));
? ? ? ? ? ? ? ? printf("device subnetMask: %sn", subnetMask);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno),?
__FILE__, __LINE__);
? ? ? ? ? ? ? ? close(fd);
? ? ? ? ? ? ? ? return -1;
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? else
? ? {
? ? ? ? printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__,?
__LINE__);
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
??
? ? close(fd);
? ? return 0;
}
??
int main(void)
{
? ? getLocalInfo();
? ? return 0;
}
使用ioctl函數(shù)雖然可以獲取所有的信息,但是使用起來(lái)比較麻煩,如果不需要
獲取MAC地址,那么使用getifaddrs函數(shù)來(lái)獲取更加方便與簡(jiǎn)潔。值得一提的是
,在MacOS或iOS系統(tǒng)上(如iPhone程序開(kāi)發(fā)),上述iotcl函數(shù)沒(méi)法獲得mac地址
跟子網(wǎng)掩碼,這個(gè)使用,使用getifaddrs函數(shù)便更有優(yōu)勢(shì)了。下面是使用
getiaddrs函數(shù)獲取網(wǎng)卡信息的C語(yǔ)言代碼實(shí)現(xiàn)。
#include <stdio.h> ?
#include <ifaddrs.h> ?
#include <arpa/inet.h> ?
??
int getSubnetMask()
{
? ? struct sockaddr_in *sin = NULL;
? ? struct ifaddrs *ifa = NULL, *ifList;
? ? if (getifaddrs(&ifList) < 0)
? ? {
? ? ? ? return -1;
? ? }
? ? for (ifa = ifList; ifa != NULL; ifa = ifa->ifa_next)
? ? {
? ? ? ? if(ifa->ifa_addr->sa_family == AF_INET)
? ? ? ? {
? ? ? ? ? ? printf("n>>> interfaceName: %sn", ifa->ifa_name);
? ? ? ? ? ? sin = (struct sockaddr_in *)ifa->ifa_addr;
? ? ? ? ? ? printf(">>> ipAddress: %sn", inet_ntoa(sin->sin_addr));
? ? ? ? ? ? sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
? ? ? ? ? ? printf(">>> broadcast: %sn", inet_ntoa(sin->sin_addr));
? ? ? ? ? ? sin = (struct sockaddr_in *)ifa->ifa_netmask;
? ? ? ? ? ? printf(">>> subnetMask: %sn", inet_ntoa(sin->sin_addr));
? ? ? ? }
? ? }
? ? freeifaddrs(ifList);
? ? return 0;
}
??
int main(void)
{
? ? getSubnetMask();
? ? return 0;
}
========
linux下獲取主機(jī)IP地址的源碼
支持多網(wǎng)卡,主要是使用ioctl函數(shù)系統(tǒng)調(diào)用實(shí)現(xiàn),通過(guò)指定設(shè)備名實(shí)現(xiàn)指定功能.
之前使用socket()函數(shù),獲取文件描述符.在此基礎(chǔ)可以很輕松的擴(kuò)展,如獲取net?
mask,MAC address等 #include stdio.h #include sys/types.
? ? ? 支持多網(wǎng)卡,主要是使用ioctl函數(shù)系統(tǒng)調(diào)用實(shí)現(xiàn),通過(guò)指定設(shè)備名實(shí)現(xiàn)指
定功能.之前使用socket()函數(shù),獲取文件描述符.在此基礎(chǔ)可以很輕松的擴(kuò)展,如
獲取net mask,MAC address等
? ? ??
? ? ? #include <stdio.h>
? ? ? #include <sys/types.h>
? ? ? #include <sys/param.h>
? ? ??
? ? ? #include <sys/ioctl.h>
? ? ? #include <sys/socket.h>
? ? ? #include <net/if.h>
? ? ? #include <netinet/in.h>
? ? ? #include <net/if_arp.h>
? ? ??
? ? ? #define MAXINTERFACES 16?
? ? ? int main(void)
? ? ? {
? ? ? ? register int fd, intrface;
? ? ? ? struct ifreq buf[MAXINTERFACES];
? ? ? ? struct ifconf ifc;
? ? ? ? if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
? ? ? ? {
? ? ? ? ? return -1;
? ? ? ? }?
? ? ? ? ifc.ifc_len = sizeof(buf);?
? ? ? ? ifc.ifc_buf = (caddr_t) buf;
? ? ? ? if (ioctl (fd, SIOCGIFCONF, (char *) &ifc) < 0)?
? ? ? ? {?
? ? ? ? ? return -1;?
? ? ? ? }
? ? ? ? intrface = ifc.ifc_len / sizeof (struct ifreq);?
? ? ? ? printf("number of interface is: %d\n",intrface);?
? ? ? ? while (intrface-- > 0)?
? ? ? ? {?
? ? ? ? ? printf ("net device %s\n", buf[intrface].ifr_name);?
? ? ? ? ? if ((ioctl (fd, SIOCGIFFLAGS, (char *) &buf[intrface])) < 0)
? ? ? ? ? {
? ? ? ? ? ? continue;?
? ? ? ? ? }?
? ? ? ? ? if (buf[intrface].ifr_flags & IFF_PROMISC)
? ? ? ? ? {?
? ? ? ? ? ? puts ("the interface is PROMISC");?
? ? ? ? ? }?
? ? ? ? ? else?
? ? ? ? ? {
? ? ? ? ? ? if (buf[intrface].ifr_flags & IFF_UP)?
? ? ? ? ? ? {
? ? ? ? ? ? ? puts("the interface status is UP");?
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? if (buf[intrface].ifr_flags & IFF_RUNNING)
? ? ? ? ? ? ? ? puts("the interface status is RUNNING");
? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ?
? ? ? ? ? if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface])))?
? ? ? ? ? {
? ? ? ? ? ? puts ("IP address is:");?
? ? ? ? ? ? puts(inet_ntoa(((struct sockaddr_in*)(&buf
[intrface].ifr_addr))->sin_addr));
? ? ? ? ? ? puts("");?
? ? ? ? ? }?
? ? ? ? ? else
? ? ? ? ? {?
? ? ? ? ? ? char str[256];?
? ? ? ? ? ? sprintf (str, "cpm: ioctl device %s", buf
[intrface].ifr_name); perror (str);
? ? ? ? ? }
? ? ? ? }
? ? ? ? close (fd);?
? ? ? ? return 0;?
? ? ? }
========
linux 系統(tǒng)獲取網(wǎng)絡(luò)ip, mask, gateway, dns信息小程序
net_util.c
? ? ? ?#define WIRED_DEV ? ? ? ? ? ? ? ? ? "eth0"?
? ? #define WIRELESS_DEV ? ? ? ? ? ? ? ?"ra0" ? ? ? ? ??
? ? #define PPPOE_DEV ? ? ? ? ? ? ? ? ? "ppp0"
#define DEBUG_PRT(fmt, arg...) ? ? ?printf(fmt,##arg)
/**
?* get ip address.
?* @param net_dev net device.
?* @param ipaddr a pointer to save ip address.
?* @return 0 success, or fail.
?*/
int get_ipaddr(const char *net_dev, ?char *ipaddr)
{
? ? struct ifreq ifr;
? ? int fd = 0;
? ? struct sockaddr_in *pAddr;
? ? if((NULL == net_dev) || (NULL == ipaddr))
? ? {
? ? ? ? DEBUG_PRT("illegal call function SetGeneralIP! \n");
? ? ? ? return -1;
? ? }
? ? if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
? ? {
? ? ? ? DEBUG_PRT("open socket failed \n");
? ? ? ? return -1;
? ? }
? ? memset(&ifr,0,sizeof(ifr));
? ? strcpy(ifr.ifr_name, net_dev);
? ? if(ioctl(fd, SIOCGIFADDR, &ifr) < 0)
? ? {
? ? ? ? DEBUG_PRT("SIOCGIFADDR socket failed \n");
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
? ? pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
? ? strcpy(ipaddr, inet_ntoa(pAddr->sin_addr));
? ??
? ? close(fd);
? ??
? ? return 0;
}
/**
?* get gateway.
?* @param gateway a pointer to save geteway.
?* @return none.
?*/
void get_gateway(ITI_CHAR *gateway)
{
? ? char buf[1024]={0};
? ? char *p = NULL;
? ? char *q = NULL;
? ? int count = 0;
? ? if(NULL == gateway)
? ? {
? ? ? ? DEBUG_PRT("gateway is NULL \n");
? ? ? ? return;?
? ? }
? ? cmd_run("route | grep default", buf, 1024);
? ? if(0 == strlen(buf))
? ? {
? ? ? ? DEBUG_PRT("get gateway error \n");
? ? ? ? return;
? ? }
? ? p = strstr2(buf, "default");
? ? q = p;
? ? while(*q == ' ')
? ? {
? ? ? ? q++;
? ? }
? ? p = q;
? ? while(*p != ' ')
? ? {
? ? ? ? p++;
? ? ? ? count++;
? ? }
? ? if(NULL != q)
? ? {
? ? ? ? memcpy(gateway, q, count);
? ? }
? ? gateway[count] = '\0'; ?
}
/**
?* get mask.
?* @param net_dev net device.
?* @param mask a pointer to save mask.
?* @return none.
?*/
void get_mask(const char *net_dev, ITI_CHAR *mask)
{
? ? char buf[1024]={0};
? ? char *p = NULL;
? ? if(NULL == mask)
? ? {
? ? ? ? DEBUG_PRT("mask is NULL \n");
? ? ? ? return;?
? ? }
? ? if(0 == (memcmp(WIRED_DEV, net_dev, sizeof(WIRED_DEV))))
? ? {
? ? ? ? cmd_run("ifconfig eth0 | grep Mask", buf, 1024);
? ? }
? ? else if(0 == (memcmp(WIRELESS_DEV, net_dev, sizeof(WIRELESS_DEV))))
? ? {
? ? ? ? cmd_run("ifconfig ra0 | grep Mask", buf, 1024);
? ? }
? ? else if(0 == (memcmp(PPPOE_DEV, net_dev, sizeof(PPPOE_DEV))))
? ? {
? ? ? ? cmd_run("ifconfig ppp0 | grep Mask", buf, 1024);
? ? }
? ? else?
? ? {
? ? ? ? DEBUG_PRT("net device not support \n");
? ? ? ? return;?
? ? }
? ??
? ? if(0 == strlen(buf))
? ? {
? ? ? ? DEBUG_PRT("get mask error \n");
? ? ? ? return;
? ? }
? ? p = strstr2(buf, "Mask:");
? ? if(NULL == p)
? ? {
? ? ? ? DEBUG_PRT("get mask error \n");
? ? ? ? return;
? ? }
? ? strcpy(mask, p);
}
/**
?* get dns.
?* @param dns1 a pointer to save first dns.
?* @param dns2 a pointer to save second dns.
?* @return 0 success, or fail.
?*/
int get_dns(char *dns1, char *dns2)
{
? ? int fd = -1;
? ? int size = 0;
? ? char strBuf[100];
? ? char tmpBuf[100];
? ? int buf_size = sizeof(strBuf);
? ? char *p = NULL;
? ? char *q = NULL;
? ? int i = 0;
? ? int j = 0;
? ? int count = 0;
? ??
? ? fd = open("/etc/resolv.conf", O_RDONLY);
? ? if(-1 == fd)
? ? {
? ? ? ? DEBUG_PRT("%s open error \n", __func__);
? ? ? ? return -1;
? ? }
? ? size = read(fd, strBuf, buf_size);
? ? if(size < 0)
? ? {
? ? ? ? DEBUG_PRT("%s read file len error \n", __func__);
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
? ? strBuf[buf_size] = '\0';
? ? close(fd);
? ? while(i < buf_size)
? ? {
? ? ? ? if((p = strstr2(&strBuf[i], "nameserver")) != NULL)
? ? ? ? {
? ? ? ? ? ? j++;
? ? ? ? ? ? p += 1;
? ? ? ? ? ? count = 0;
? ? ? ? ? ??
? ? ? ? ? ? memset(tmpBuf, 0xff, 100);
? ? ? ? ? ? memcpy(tmpBuf, p, 100);
? ? ? ? ? ? tmpBuf[sizeof(tmpBuf) -1 ] = '\0';
? ? ? ? ? ??
? ? ? ? ? ? q = p;
? ? ? ? ? ? while(*q != '\n')
? ? ? ? ? ? {
? ? ? ? ? ? ? ? q++;
? ? ? ? ? ? ? ? count++;
? ? ? ? ? ? }
? ? ? ? ? ? i += (sizeof("nameserver") + count);
? ? ? ? ? ??
? ? ? ? ? ? if(1 == j)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? memcpy(dns1, p, count);
? ? ? ? ? ? ? ? dns1[count]='\0';
? ? ? ? ? ? }
? ? ? ? ? ? else if(2 == j)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? memcpy(dns2, p, count);
? ? ? ? ? ? ? ? dns2[count]='\0';
? ? ? ? ? ? }
? ? ? ? }?
? ? ? ? else?
? ? ? ? {
? ? ? ? ? ? i++;
? ? ? ? }
? ? }
? ? return 0;
}
main.c
void main(void)
{
? ? ? ? #define WIRED_DEV ? ? ? ? ? ? ? ? ? "eth0"?
? ? #define WIRELESS_DEV ? ? ? ? ? ? ? ?"ra0" ? ? ? ? ??
? ? #define PPPOE_DEV ? ? ? ? ? ? ? ? ? "ppp0"
? ? ? ? char buf[1024] = {'\0'};
? ? extern int get_ipaddr(const char *net_dev, ?char *ipaddr);
? ? get_ipaddr(WIRED_DEV, buf);
? ? printf("get_ipaddr: %s \n", buf);
? ? memset(buf, '\0', sizeof(buf));
? ??
? ? extern void get_mask(const char *net_dev, ITI_CHAR *mask);
? ? get_mask(WIRED_DEV, buf);
? ? printf("get_mask: %s \n", buf);
? ? memset(buf, '\0', sizeof(buf));
? ??
? ? extern void get_gateway(ITI_CHAR *gateway);
? ? get_gateway(buf);
? ? printf("get_gateway: %s \n", buf);
? ? memset(buf, '\0', sizeof(buf));
? ? extern int get_dns(char *dns1, char *dns2);
? ? get_dns(buf, &buf[100]);
? ? printf("get_dns: %s %s\n", buf, &buf[100]);
? ? memset(buf, '\0', sizeof(buf));
}
makefile:
gcc main.c net_util.c -o get_net_info
./get_net_info
運(yùn)行結(jié)果:
get_ipaddr: 192.168.9.142?
get_mask: 255.255.255.0
get_gateway: 192.168.9.254?
get_dns: 192.168.9.11 192.168.9.10
為提高執(zhí)行效率, 更新獲取網(wǎng)關(guān)和子網(wǎng)掩碼程序:
static void get_gateway(const char *net_dev, char *gateway)
{
? ? FILE *fp; ? ?
? ? char buf[1024]; ?
? ? char iface[16]; ? ?
? ? unsigned char tmp[100]={'\0'};
? ? unsigned int dest_addr=0, gate_addr=0;
? ? if(NULL == gateway)
? ? {
? ? ? ? DEBUG_PRT("gateway is NULL \n");
? ? ? ? return;?
? ? }
? ? fp = fopen("/proc/net/route", "r"); ? ?
? ? if(fp == NULL){ ?
? ? ? ? DEBUG_PRT("fopen error \n");
? ? ? ? return; ??
? ? }
? ??
? ? fgets(buf, sizeof(buf), fp); ? ?
? ? while(fgets(buf, sizeof(buf), fp))?
? ? { ? ?
? ? ? ? if((sscanf(buf, "%s\t%X\t%X", iface, &dest_addr, &gate_addr) == 3)?
? ? ? ? ? ? && (memcmp(net_dev, iface, strlen(net_dev)) == 0)
? ? ? ? ? ? && gate_addr != 0)?
? ? ? ? {
? ? ? ? ? ? ? ? memcpy(tmp, (unsigned char *)&gate_addr, 4);
? ? ? ? ? ? ? ? sprintf(gateway, "%d.%d.%d.%d", (unsigned char)*tmp, (unsigned char)*(tmp+1), (unsigned char)*(tmp+2), (unsigned char)*(tmp+3));
? ? ? ? ? ? ? ? break; ? ?
? ? ? ? }
? ? } ? ?
? ? ??
? ? fclose(fp);
}
static void get_mask(const char *net_dev, ITI_CHAR *mask)
{
? ? struct sockaddr_in *pAddr;
? ? struct ifreq ifr;
? ? int sockfd;
? ? sockfd = socket(AF_INET,SOCK_DGRAM,0);
? ? memset(&ifr,0,sizeof(ifr));
? ? strcpy(ifr.ifr_name, net_dev);
? ??
? ? if(ioctl(sockfd, SIOCGIFNETMASK, &ifr) < 0){
? ? ? ? DEBUG_PRT("SIOCGIFADDR socket failed \n");
? ? ? ? close(sockfd);
? ? ? ? return ;
? ? }
? ? pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
? ? strcpy(mask, (char *)(inet_ntoa(pAddr->sin_addr)));
? ??
? ? close(sockfd);
}
========
Linux環(huán)境編程:獲取網(wǎng)卡的實(shí)時(shí)網(wǎng)速
?
在Windows下面,我們可以看到360或者是qq安全衛(wèi)士的“安全球”,上面顯示實(shí)時(shí)的網(wǎng)速情況。那么在Linux里面如何獲取網(wǎng)卡的實(shí)時(shí)網(wǎng)速?其實(shí)原理很簡(jiǎn)單,讀取需要獲取網(wǎng)速的網(wǎng)卡在某段時(shí)間dT內(nèi)流量的變化dL,那么實(shí)時(shí)網(wǎng)速就出來(lái)了,Speed = dL / dt。
Linux在ifaddrs.h中提供了函數(shù):
/* Create a linked list of `struct ifaddrs' structures, one for each
? network interface on the host machine. ?If successful, store the
? list in *IFAP and return 0. ?On errors, return -1 and set `errno'.
? ? ? ? ? ??
? The storage returned in *IFAP is allocated dynamically and can
? only be properly freed by passing it to `freeifaddrs'. ?*/
extern int getifaddrs (struct ifaddrs **__ifap) __THROW;
? ? ? ? ??
/* Reclaim the storage allocated by a previous `getifaddrs' call. ?*/
extern void freeifaddrs (struct ifaddrs *__ifa) ?__THROW;
系統(tǒng)會(huì)創(chuàng)建一個(gè)包含本機(jī)所有網(wǎng)卡信息鏈表,然后我們就可以在這個(gè)鏈表里面獲取我們想要的信息。
/* The `getifaddrs' function generates a linked list of these structures.
? Each element of the list describes one network interface. ?*/
struct ifaddrs
{
? struct ifaddrs *ifa_next; /* Pointer to the next structure. ?*/
? char *ifa_name; ? ? ?/* Name of this network interface. ?*/
? unsigned int ifa_flags; ?/* Flags as from SIOCGIFFLAGS ioctl. ?*/
? struct sockaddr *ifa_addr; ? ?/* Network address of this interface. ?*/
? struct sockaddr *ifa_netmask; /* Netmask of this interface. ?*/
? union
? {
? ? /* At most one of the following two is valid. ?If the IFF_BROADCAST
? ? ? bit is set in `ifa_flags', then `ifa_broadaddr' is valid. ?If the
? ? ? IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.
? ? ? It is never the case that both these bits are set at once. ?*/
? ? struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */
? ? struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. ?*/
? } ifa_ifu;
? /* These very same macros are defined by <net/if.h> for `struct ifaddr'.
? ? So if they are defined already, the existing definitions will be fine. ?*/
# ifndef ifa_broadaddr
# ?define ifa_broadaddr ifa_ifu.ifu_broadaddr
# endif
# ifndef ifa_dstaddr
# ?define ifa_dstaddr ?ifa_ifu.ifu_dstaddr
# endif?
? ? ? ??
? void *ifa_data; ? ? ?/* Address-specific data (may be unused). ?*/
};
另外這個(gè)鏈表我們是可以提前用ioctl來(lái)篩選的,可以通過(guò)ifa_name和ifa_flags來(lái)確定ifa_ifu里面到底選用那個(gè)union。不過(guò)這次我們是來(lái)測(cè)量實(shí)時(shí)網(wǎng)速的,不必要關(guān)心這個(gè)。
我們需要關(guān)心的是ifa_data這個(gè)項(xiàng),關(guān)于這個(gè)項(xiàng)我百度了很多,一直沒(méi)有發(fā)現(xiàn)他到底應(yīng)該屬于哪個(gè)結(jié)構(gòu)體的。
后來(lái)無(wú)意在 http://www.linuxidc.com/Linux/2014-11/109289.htm 發(fā)現(xiàn)有類似的,但是我找不到頭文件在那,所以后來(lái)干脆我直接把他放到我的頭文件里面;
struct if_data{
?/* generic interface information */
?u_char ifi_type; /* ethernet, tokenring, etc */
?u_char ifi_addrlen; /* media address length */
?u_char ifi_hdrlen; /* media header length */
?u_long ifi_mtu; /* maximum transmission unit */
?u_long ifi_metric; /* routing metric (external only) */
?u_long ifi_baudrate; /* linespeed */
?/* volatile statistics */
?u_long ifi_ipackets; /* packets received on interface */
?u_long ifi_ierrors; /* input errors on interface */
?u_long ifi_opackets; /* packets sent on interface */
?u_long ifi_oerrors; /* output errors on interface */
?u_long ifi_collisions; /* collisions on csma interfaces */
?u_long ifi_ibytes; /* total number of octets received */
?u_long ifi_obytes; /* total number of octets sent */
?u_long ifi_imcasts; /* packets received via multicast */
?u_long ifi_omcasts; /* packets sent via multicast */
?u_long ifi_iqdrops; /* dropped on input, this interface */
?u_long ifi_noproto; /* destined for unsupported protocol */
?struct timeval ifi_lastchange;/* last updated */
};
剛剛開(kāi)始我就打印了ifi_iobytes,ifi_obytes這兩個(gè)項(xiàng),不管我怎么下載和上次文件,這兩個(gè)量都是0。糾結(jié)了我半天,我就直接把所有變量都打印出來(lái),發(fā)現(xiàn)ifi_mtu,ifi_metric,ifi_baudrate跟ifconfig eth0輸出的數(shù)據(jù)很像。
[15:12 @ ~/program/netspeed]$ ifconfig eth0
eth0 ? ? ?Link encap:Ethernet ?HWaddr 00:22:15:67:F8:16 ?
? ? ? ? ? inet addr:210.42.158.204 ?Bcast:210.42.158.255 ?Mask:255.255.255.0
? ? ? ? ? inet6 addr: fe80::222:15ff:fe67:f816/64 Scope:Link
? ? ? ? ? UP BROADCAST RUNNING MULTICAST ?MTU:1500 ?Metric:1
? ? ? ? ? RX packets:917978 errors:0 dropped:0 overruns:0 frame:0
? ? ? ? ? TX packets:1132894 errors:0 dropped:0 overruns:0 carrier:0
? ? ? ? ? collisions:0 txqueuelen:1000?
? ? ? ? ? RX bytes:132866544 (126.7 MiB) ?TX bytes:1250785627 (1.1 GiB)
? ? ? ? ? Interrupt:29 Base address:0x4000
慢慢的我知道了規(guī)律,struct ifaddrs里面的ifa_data前四個(gè)字(32位)以此是發(fā)送數(shù)據(jù)包數(shù),接收數(shù)據(jù)包數(shù),發(fā)送字節(jié)數(shù),接收字節(jié)數(shù)。
我就重新調(diào)整了struct if_data的結(jié)構(gòu)體,由于后面的數(shù)據(jù)全為0,我就保留了4項(xiàng):
struct if_data
{ ?
? ? /* ?generic interface information */
? ? u_long ifi_opackets; ? ?/* ?packets sent on interface */
? ? u_long ifi_ipackets; ? ?/* ?packets received on interface */
? ? u_long ifi_obytes; ? ? ?/* ?total number of octets sent */
? ? u_long ifi_ibytes; ? ? ?/* ?total number of octets received */
};?
測(cè)試OK。
[15:17 @ ~/program/netspeed]$ ./netspeed?
Get eth0 Speed ? ? ? ? ? ? ? ? ?[OK]
eth0: Up Speed: 1.671066 MB/s || Down Speed: 0.036335 MB/s
附上我已經(jīng)封裝好的代碼:
int get_if_dbytes(struct if_info* ndev)
{ ?
? ? assert(ndev);
? ??
? ? struct ifaddrs *ifa_list = NULL;
? ? struct ifaddrs *ifa = NULL;
? ? struct if_data *ifd = NULL;
? ? int ? ?ret = 0;
? ??
? ? ret = getifaddrs(&ifa_list);
? ? if(ret < 0) {?
? ? ? ? perror("Get Interface Address Fail:");
? ? ? ? goto end;
? ? } ?
? ??
? ? for(ifa=ifa_list; ifa; ifa=ifa->ifa_next){
? ? ? ? if(!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING))
? ? ? ? ? ? continue;
? ? ? ? if(ifa->ifa_data == 0)
? ? ? ? ? ? continue;
? ? ? ??
? ? ? ? ret = strcmp(ifa->ifa_name,ndev->ifi_name);
? ? ? ? if(ret == 0){
? ? ? ? ? ifd = (struct if_data *)ifa->ifa_data;
? ? ? ? ??
? ? ? ? ? ndev->ifi_ibytes = ifd->ifi_ibytes;
? ? ? ? ? ndev->ifi_obytes = ifd->ifi_obytes;
? ? ? ? ? break;
? ? ? ? }
? ? }
? ? freeifaddrs(ifa_list);
end:
? ? return (ret ? -1 : 0);
}
int get_if_speed(struct if_speed *ndev)
{
? ? assert(ndev);
? ? struct if_info *p1=NULL,*p2=NULL;
? ? p1 = (struct if_info *)malloc(sizeof(struct if_info));
? ? p2 = (struct if_info *)malloc(sizeof(struct if_info));
? ? bzero(p1,sizeof(struct if_info));
? ? bzero(p2,sizeof(struct if_info));
? ? strncpy(p1->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));
? ? strncpy(p2->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));
? ? int ret = 0;
? ? ret = get_if_dbytes(p1);
? ? if(ret < 0) ? ?goto end;
? ? usleep(ndev->ifs_us);
? ? ret = get_if_dbytes(p2);
? ? if(ret < 0) ? ?goto end;
? ? ndev->ifs_ispeed = p2->ifi_ibytes - p1->ifi_ibytes;
? ? ndev->ifs_ospeed = p2->ifi_obytes - p1->ifi_obytes;
end:
? ? free(p1);
? ? free(p2);
? ? return 0;
}
頭文件:
#ifndef __TSPEED_H__
#define __TSPEED_H__
#ifdef __cplusplus
extern "C"
{
#endif
? ??
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <error.h>
? ? /* For "open" function */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct if_data
{ ?
? ? /* ?generic interface information */
? ? u_long ifi_opackets; ? ?/* ?packets sent on interface */
? ? u_long ifi_ipackets; ? ?/* ?packets received on interface */
? ? u_long ifi_obytes; ? ? ?/* ?total number of octets sent */
? ? u_long ifi_ibytes; ? ? ?/* ?total number of octets received */
};
? ??
struct if_info
{ ?
? ? char ifi_name[16];
? ? unsigned long ifi_ibytes;
? ? unsigned long ifi_obytes;
};
struct if_speed
{ ?
? ? char ifs_name[16];
? ? unsigned long ifs_ispeed;
? ? unsigned long ifs_ospeed;
? ? unsigned long ifs_us;
};
extern int get_if_dbytes(struct if_info *ndev);
extern int get_if_speed(struct if_speed *ndev);
#ifdef __cplusplus
}
#endif
#endif
測(cè)試代碼:
int main (int argc, char **argv)
{
? ? struct if_speed ndev;
? ? int ret = 0;
? ? bzero(&ndev,sizeof(ndev));
? ? sprintf(ndev.ifs_name,"eth0");
? ? ndev.ifs_us = 100000;
? ? printf("Get %s Speed");
? ? ret = get_if_speed(&ndev);
? ? if(ret < 0)
? ? ? ? printf("\t\t\t[Fail]\n");
? ? else
? ? ? ? printf("\t\t\t[OK]\n");
? ? float ispeed ,ospeed;
? ? while(1){
? ? ? ? ispeed = ndev.ifs_ispeed * 1.0/(ndev.ifs_us/1000 * 0.001);
? ? ? ? ospeed = ndev.ifs_ospeed * 1.0/(ndev.ifs_us/1000 * 0.001);
? ? ? ? printf("%s: Up Speed: %f MB/s || Down Speed: %f MB/s ? ? ? ? ? ? ? ? ?\r",
? ? ? ? ? ? ? ? ndev.ifs_name,ispeed/(1024.0*1024.0),ospeed/(1024.0*1024.0));
? ? ? ? get_if_speed(&ndev);
? ? }
? ? return 0;
} /* ----- End of main() ----- */
可能你有更好的獲取網(wǎng)速的辦法,求留言指點(diǎn)!
========
相關(guān)鏈接
http://blog.csdn.net/taiyang1987912/article/details/46010923linux編程獲取網(wǎng)絡(luò)信息
總結(jié)
以上是生活随笔為你收集整理的Linux编程获取网络信息总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux字符驱动开发学习总结
- 下一篇: 图解协议之图集