Linux 下無需調用複雜的 ioctl/netlink,直接讀取 /proc/net/dev 即可獲取各網卡接收/發送字節數、包數、錯誤數等統計。本文提供完整 C 實現,解析文件格式、字段映射、單位換算,並給出可直接編譯運行的代碼。
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
eth0: 123456 789 0 0 0 0 0 0 654321 456 0 0 0 0 0 0
lo: 11111 22 0 0 0 0 0 0 11111 22 0 0 0 0 0 0
接口名: + 16 個數值(前 8 個 Receive,後 8 個 Transmit)。long *get_iface_stats(const char *iface) {
static long stats[2]; // [0]=Rx, [1]=Tx
FILE *fp = fopen("/proc/net/dev", "r");
if (!fp) return NULL;
char line[512];
fgets(line, sizeof(line), fp); // skip header 1
fgets(line, sizeof(line), fp); // skip header 2
while (fgets(line, sizeof(line), fp)) {
char name[32];
unsigned long rx_bytes, tx_bytes;
// 格式: " eth0: 12345 678 ... 98765 432 ..."
if (sscanf(line, " %31[^:]: %lu %*u %*u %*u %*u %*u %*u %*u %lu",
name, &rx_bytes, &tx_bytes) == 3) {
if (strcmp(name, iface) == 0) {
stats[0] = rx_bytes;
stats[1] = tx_bytes;
fclose(fp);
return stats;
}
}
}
fclose(fp);
return NULL;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long *get_iface_stats(const char *iface); // 上文實現
int main(int argc, char *argv[]) {
const char *iface = (argc > 1) ? argv[1] : "eth0";
long *stats = get_iface_stats(iface);
if (!stats) {
fprintf(stderr, "Interface %s not found or read error\n", iface);
return 1;
}
printf("%s: RX = %.2f MB, TX = %.2f MB\n",
iface,
stats[0] / (1024.0 * 1024.0),
stats[1] / (1024.0 * 1024.0));
return 0;
}
gcc -Wall -o netstat netstat.c ./netstat eth0 # 輸出示例:eth0: RX = 12.34 MB, TX = 56.78 MB
struct iface_stats { uint64_t rx_bytes, tx_bytes, rx_packets, tx_packets, rx_errs, tx_errs, ... }。speed = (curr - prev) / interval。sysctl 或 libstatgrab。netlink (NETLINK_ROUTE) 訂閱內核通知,避免輪詢開銷。/proc/net/dev 字段單位均為**字節**,非位/包。docker0、veth* 等也會出現,按需過濾。/proc/net/dev 通常無需 root,但某些加固系統可能限制。