C实现的 CENTOS宽带监控小程序

/*
*	Centos服务器宽带监控程序
*	
*	使用方法:
*		首先在新建/etc/rate.d/目录 并且赋予0777权限
*		运行本程序 会在上述提到的目录中 创建 hour.json 和 minute.json 文件 
*		前者记录 当天24小时 的宽带流速 后者记录 30分钟以内宽带流速(均为平均值)
*		RX是下行  TX是上行 对应的数据 *8/1024/1024 得到即为 Mbps/s
*		数据以JSON的格式保存
*		程序有诸多不完善之处 还望大虾自己研究 修改
*
*/
#include <stdio.h> 
#include <string.h> 
#include <time.h> 
#include <stdlib.h>
#include <signal.h>


#define SLEEP_TIME 1


char* get(char* str);
char* getstr();
void getinfo(char* line);
void start();
void start_service();

struct dev{
	char devname[128];
	long info[16];
};

struct RATE_LOG{
	int day ;
	int hour;
	int minute;
	int second;
	long rx;
	long tx;
};

char * pTmp;
struct dev eth0;

struct RATE_LOG minute_bw[30];
struct RATE_LOG hour_bw[24];

long last_tx = 0;
long last_rx = 0;



int main(){
	
	signal(SIGCLD, SIG_IGN);//通知内核 子进程一旦结束立即释放资源
	
	printf("Centos 实时宽带检测系统 测试版\n");
	pid_t fpid = fork();
	if(fpid == 0){
		start_service();
	}
	printf("\n流控监控服务     [已启动]\nPID:        %d\n",fpid);
	return 0;
}

void start_service(){
	int d = 0;
	int last_day = 0;
	int last_minute = 0;
	int last_second = 0;
	int last_hour = 0;
		
	int minute = 0;
	int day = 0;
	int hour = 0;
	
	long hour_rx_count = 0;
	long hour_tx_count = 0;
		
	time_t timep;  
	struct tm *p;  
	int j;
	
	/*
		初始化 分钟宽带 监控数据
	*/
	for(j=0;j<30;j++){
		minute_bw[j].rx = 0;
		minute_bw[j].tx = 0;
		minute_bw[j].minute = 0;
		minute_bw[j].hour = 0;
		
	}
	
	/*
		初始化 小时宽带 监控数据
	*/
	for(j=0;j<24;j++){
		hour_bw[j].hour = j+1;
		hour_bw[j].rx = 0;
		hour_bw[j].tx = 0;
	}
	
	
	time(&timep);  
	p = localtime(&timep);
	last_minute = p->tm_min;
	last_day = p->tm_mday;
	last_hour = p->tm_hour;
		
	start();

	last_rx = eth0.info[0];
	last_tx = eth0.info[8];
	
	int k = 0;//一共逝去了多少分钟
	
	//system("clear");
	while(1){	
	
		time(&timep);  
		p = localtime(&timep);
		minute = p->tm_min;
		day = p->tm_mday;
		hour = p->tm_hour;
		
		if(minute != last_minute)
		{
			//过去了一分钟
			int rx_bw = (eth0.info[0] - last_rx)/60; //计算得出下行宽带平均每秒钟使用的流量
			int tx_bw = (eth0.info[8] - last_tx)/60;  //计算得出上行宽带平均每秒钟使用的流量
			
			hour_rx_count += rx_bw;
			hour_tx_count += tx_bw;
			
			
			last_rx = eth0.info[0];
			last_tx = eth0.info[8];
			int i;
			for(i=0;i<29;i++){
				minute_bw[i] = minute_bw[i+1];
			}
			minute_bw[29].rx = rx_bw;
			minute_bw[29].tx = tx_bw;
			minute_bw[29].minute = minute;
			minute_bw[29].hour = hour;
			if(fork() == 0){
				//格式化成JSON数据保存 之所以在单独的线程中 是为了尽量避免影响流量统计的延时
				char buffer[512];
				FILE *fp = fopen("/etc/rate.d/minute.json","w");
				fputs("{",fp);
				for(i=0;i<30;i++){
					if(i == 29){
						sprintf(buffer,"\"%d:%d\":{\"rx\":\"%d\",\"tx\":\"%d\"}\n",minute_bw[i].hour,minute_bw[i].minute,minute_bw[i].rx,minute_bw[i].tx);
					}else{
						sprintf(buffer,"\"%d:%d\":{\"rx\":\"%d\",\"tx\":\"%d\"},\n",minute_bw[i].hour,minute_bw[i].minute,minute_bw[i].rx,minute_bw[i].tx);
					}
					fputs(buffer,fp);
				}
				fputs("}",fp);
				fclose(fp);
				exit(getpid());
			}
			k++;
		}
		
		if(hour != last_hour){
			hour_bw[hour-1].hour = hour;
			hour_bw[hour-1].rx = hour_rx_count / k; 
			hour_bw[hour-1].tx = hour_tx_count / k;
			k=0;
			hour_rx_count = 0;
			hour_tx_count = 0;
			if(fork() == 0){
				//格式化成JSON数据保存 之所以在单独的线程中 是为了尽量避免影响流量统计的延时
				int i;
				char buffer[512];
				FILE *fp = fopen("/etc/rate.d/hour.json","w");
				fputs("{",fp);
				for(i=0;i<24;i++){
					if(i == 23){
						sprintf(buffer,"\"%d\":{\"rx\":\"%d\",\"tx\":\"%d\"}\n",hour_bw[i].hour,hour_bw[i].rx,hour_bw[i].tx);
					}else{
						sprintf(buffer,"\"%d\":{\"rx\":\"%d\",\"tx\":\"%d\"},\n",hour_bw[i].hour,hour_bw[i].rx,hour_bw[i].tx);
					}
					fputs(buffer,fp);
				}
				fputs("}",fp);
				fclose(fp);
				exit(getpid());
			}
		}
		
		
		last_day = day;
		last_minute = minute;
		last_hour = hour;
		start();
		sleep(SLEEP_TIME);
		
	}
}

//解析/proc/net/dev文件 并将流量数据格式化 这里的识别逻辑有待优化
void start(){
	
	char buffer[1024];
	FILE *fp = fopen("/proc/net/dev","r");
	fgets(buffer,1024,fp);
	fgets(buffer,1024,fp);
	while(fgets(buffer,1024,fp)){
		char *p = strstr(buffer,"tun");
		if(NULL == strstr(buffer,"tun") && NULL == strstr(buffer,"lo"))
		{
			//排除虚拟网卡和lo网卡 剩下的应该就是真实的网卡了
			getinfo(buffer);
			break; //跳出循环 不统计内网网卡
		} 	
		//strstr
	}
	fclose(fp);


}

//解析信息并放置到结构体当中
void getinfo(char* line){
	strcpy(eth0.devname,get(line));
	int i = 0;
	for(i=0;i<16;i++){
		eth0.info[i] = strtol(getstr(),(char**)NULL,10);
	//	printf("%d ",eth0.info[i]);
	}
	
}

char* get(char* str){
	pTmp = str;
	return getstr();
}

char* getstr(){
	char* pStr = pTmp;
	//int len = strlen(str); 
	while(*pTmp == ' '){
		pTmp++;
	} 
	while(*pTmp != '\0'){
		if(*pTmp == ' '){
			*pTmp = '\0';
			break;
		}
		pTmp++;
	
	}
	pTmp++;
	return pStr;
}

程序非常小巧,直接gcc 编译即可。使用方法请看头部注释。

请大神 不用直接用在生产环境 务必要修改优化 仅供参考 欢迎提供指正!


我的邮箱 admin@dingd.cn也欢迎一起交流。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值