网络监测服务之获取ping丢包率
一直在买VPS,但是对于网络的质量监测却从来也没在意过。这次想动手搭建一个简单的监测系统。
架构很简单

获取被监测节点到目标IP的Ping丢包率,然后通过tcp socket的方式传给web站点,由web站点的服务处理入库,最终以web页面的方式展示出来。
被监测节点到web站点之间用kcptun通讯,这种方式使用UDP快速,另外我不会加密tcp socket,直接用kcptun来做加密了。
第一步就是如何获取Ping的丢包结果
ping -c 1000 -f 8.8.8.8 | awk 'NR==4 {print $6}'-c 指定Ping包的数量-f 使用最快的方式发包NR==4 获取第4行{print $6} 此例中awk命令以空格或TAB键来分隔字符串,{print $6}表示打印分隔后的第6组数据
之后会得到一个带%的结果:0.9%
第二步就是如何通过C语言来获取这样的结果
因为ping是一个已经存在系统中的命令,首先想到使用exec系列的函数,但是后面的awk怎么处理呢?又会涉及到子进程,父进程之间通信的问题。两个简单的命令暂时不想这么复杂。
通过搜索,找到了popen函数 参考:C语言popen()函数:建立管道I/O,于是就可以写成
#include <stdio.h>
int main()
{
FILE * fp;
char buffer[5];
fp = popen("ping -c 1000 -f 8.8.8.8 | awk 'NR==4 {print $6}'", "r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
return 0;
}加上-std=c11编译之后会出错warning: implicit declaration of function ‘popen’,原因是popen is not part of C,解决方法,加上#define _GNU_SOURCE 详见Why does -std=c11 with gcc hide popen in stdio.h?
#define _GNU_SOURCE
#include <stdio.h>
int main()
{
FILE * fp;
char buffer[5];
fp = popen("ping -c 1000 -f 8.8.8.8 | awk 'NR==4 {print $6}'", "r");
fgets(buffer, sizeof(buffer), fp);
printf("%s", buffer);
pclose(fp);
return 0;
}输出0.9%
第三步,需要把%去掉,使用strtok_r函数
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE * fp;
char buffer[5];
// 函数原型 char *strtok_r(char *str, const char *delim, char **saveptr);
const char * const delim = "%"; // 分隔符
char *saveptr = NULL;
char *substr = NULL;
fp = popen("ping -c 1000 -f 8.8.8.8 | awk 'NR==4 {print $6}'", "r");
fgets(buffer, sizeof(buffer), fp);
pclose(fp);
printf("%s\n",buffer);
substr = strtok_r(buffer, delim, &saveptr);
printf("%s\n",substr);
return 0;
}输出0.9,但是这里的数值只是字符串类型的,还需要转成真正的数值
第四步,将string形式的数值转成int或float形式,参考:Converting Strings to Numbers in C/C++
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE * fp;
char buffer[5];
float result;
// strtok_r 相关
const char * const delim = "%"; // 分隔符
char *saveptr = NULL;
char *substr = NULL;
fp = popen("ping -c 1000 -f 8.8.8.8 | awk 'NR==4 {print $6}'", "r");
fgets(buffer, sizeof(buffer), fp);
pclose(fp);
// 以 % 分隔字符串
substr = strtok_r(buffer, delim, &saveptr);
// 将string类型数值转成float类型
sscanf(substr, "%f", &result);
printf("\nThe value of x : %0.1f\n", result); // 0.1 保留1位小数
return 0;
}输出0.9
通过以上四步,在C语言中获取Ping的丢包率,并以float类型输出结果
评论已关闭