Linux环境编程:获取网卡的实时网速

在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输出的数据很像。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/5559c2cd249e14d723739add823d2e93.html