c/c++实现linux下各个网络流量抓取

一、实现基础

        在Linux系统中,操作系统屏蔽了用户直接访问系统内核,提供了LKM机制间接在内核空间工作,在LKM机制中一个重要的组成部分就是proc伪文件系统,它为用户提供了动态操作Linux内核信息的接口。linux各个网卡(包含虚拟网卡)信息通过/proc/net/dev文件句柄进行访问获取,例如,采用cat命令读取相关信息,如下:

[py@pyfree net_info_test]$ cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:     264       4    0    0    0     0          0         0      264       4    0    0    0     0       0          0
virbr0-nic:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
virbr0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
 ens33:   75477     809    0    0    0     0          0         0   216531     679    0    0    0     0       0          0
[py@pyfree net_info_test]$

        另外借助awk命令, 可以通过 print、printf 将数据输出到标准输出或重定向到文件

[py@pyfree ~]$ cat /proc/net/dev |awk '{ if(NR!=1 && NR!=2) print $0 }' |sed 's/:/ /g'| awk '{ print($1,$2,$3,$5,$10,$11,$13)}'
lo 264 4 0 264 4 0
virbr0-nic 0 0 0 0 0 0
virbr0 0 0 0 0 0 0
ens33 89565 878 0 227278 746 0
[pyg@pyfree ~]$ 

        显然c/c++读取网卡流量信息,就是打开/proc/net/dev管道文件句柄,识别该文件内容格式,从中读取到需要的数据信息。

二、代码实现

        工程设计:

net_info_test
    bin
    src
        net.h
        net.cpp
        main.cpp
    Makefile

        net.h,定义流量信息结构体,通过popen打开/proc/net/dev获取流量信息

#ifndef _NET_INFO_H_
#define _NET_INFO_H_
/**********************************************************************************
  *Copyright 2020-09-28, pyfree
  *
  *File Name       : net.h
  *File Mark       : 
  *Summary         : 
  *
  *Current Version : 1.00
  *Author          : pyfree
  *FinishDate      :
  *
  *Replace Version :
  *Author          :
  *FinishDate      :

 ***********************************************************************************/
 #include <inttypes.h>
 
typedef struct 
{
	char netName[32];
	uint64_t recvPackets;
	uint64_t sendPackets;
	uint64_t recvBytes;
	uint64_t sendBytes;
	uint32_t recvDropPackets;
	uint32_t sendDropPackets;
}NetFlowInfo;

void getNetFlowInfo(NetFlowInfo &nfi);

#endif //_NET_INFO_H_

net.cpp

#include <string.h>
#include <stdio.h>
#include "net.h"

#define CMD "/bin/cat /proc/net/dev |awk \'{ if(NR!=1 && NR!=2) print $0 }\' |sed 's/:/ /g'| awk \'{ print $1\" \"$2\" \"$3\" \"$5\" \"$10\" \"$11\" \"$13}\'"

void getNetFlowInfo(NetFlowInfo &nfi)
{
	FILE *fp = popen(CMD, "r");
	if(fp == NULL) {
		return ;
	}
	
	NetFlowInfo stTmp;
	bool bUseComm0 = false;
	bool bUseComm1 = false;
	while( fscanf(fp,"%s%" PRIu64"%" PRIu64"%u%" PRIu64"%" PRIu64"%u",
		stTmp.netName, &stTmp.recvBytes, &stTmp.recvPackets, &stTmp.recvDropPackets, 
		&stTmp.sendBytes, &stTmp.sendPackets, &stTmp.sendDropPackets) == 7)
	{
		if(strstr(stTmp.netName, nfi.netName)){	
			memcpy(&nfi, &stTmp, sizeof(stTmp));
		}
	}
	pclose(fp);
}

main.cpp,可以自行依据运行环境修改需要监测的网络名称

#include <stdio.h>
#include <string.h>
#include "net.h"

int main(int argc, char* argv[])
{
	NetFlowInfo sfi = {0};
    //自行依据运行环境修改需要监测的网络名称,可以ifconfig先查看有那些网络名
	strncpy(sfi.netName, "ens33", sizeof(sfi.netName));
	getNetFlowInfo(sfi);
	printf("\nread inter:%s, \nrecv - \nbytes:%" PRIu64" \npackets:%" PRIu64" \ndrop:%u ; \nsend - "
				"\nbytes:%" PRIu64" \npackets:%" PRIu64" \ndrop:%u ;", 
				sfi.netName, sfi.recvBytes,  sfi.recvPackets, sfi.recvDropPackets,
				sfi.sendBytes, sfi.sendPackets, sfi.sendDropPackets);
	//system("read");
	return 0;
}

三、编译

Makefile

#/bin/sh
CX= g++ 

BIN 		:= ./bin
TARGET      := net_test.bin
FLAGS		:= -std=c++11 
#-static 
SRCDIR 		:= ./src
#INCLUDES
INCLUDEDIR 	:= -I"$(SRCDIR)"

source		:= $(wildcard $(SRCDIR)/*.cpp)

$(TARGET) :
	$(CX) $(FLAGS) $(INCLUDEDIR) $(source)  -o $(BIN)/$(TARGET)

clean:
	rm  $(BIN)/$(TARGET)

编译及输出结果:

[py@pyfree net_info_test]$ make
g++  -std=c++11  -I"./src" ./src/net.cpp ./src/main.cpp  -o ./bin/net_test.bin
[py@pyfree net_info_test]$ ./bin/net_test.bin

read inter:ens33,
recv -
bytes:95854
packets:950
drop:0 ;
send -
bytes:236500
packets:794
drop:0 ;
[py@pyfree net_info_test]$

注:类似地,可以实现对linux系统其他系统信息的实时读取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

py_free-物联智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值