在Windows下面,我们可以看到360或者是qq安全卫士的“安全球”,上面显示实时的网速情况。那么在Linux里面如何获取网卡的实时网速?其实原理很简单,读取需要获取网速的网卡在某段时间dT内流量的变化dL,那么实时网速就出来了,Speed = dL / dt。
Linux在ifaddrs.h中提供了函数:
/* 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;
系统会创建一个包含本机所有网卡信息链表,然后我们就可以在这个链表里面获取我们想要的信息。
/* 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). */
};
另外这个链表我们是可以提前用ioctl来筛选的,可以通过ifa_name和ifa_flags来确定ifa_ifu里面到底选用那个union。不过这次我们是来测量实时网速的,不必要关心这个。
我们需要关心的是ifa_data这个项,关于这个项我百度了很多,一直没有发现他到底应该属于哪个结构体的。
后来无意在 发现有类似的,但是我找不到头文件在那,所以后来干脆我直接把他放到我的头文件里面;
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 */
};
刚刚开始我就打印了ifi_iobytes,ifi_obytes这两个项,不管我怎么下载和上次文件,这两个量都是0。纠结了我半天,我就直接把所有变量都打印出来,发现ifi_mtu,ifi_metric,ifi_baudrate跟ifconfig eth0输出的数据很像。