最近在做视频直播,需要在直播断开的时候自动重新发起重连。原因可能由于摄像头rtsp服务器异常断开,或者网络原因需要重启发起直播请求。
解决思路
文件 /proc/xx/net/snmp,里面保存着实时的网络通讯数据,通过 cat /proc/xx/net/snmp 命令可以查看其内容。但是由于其内容不容易查看,实际输出如下
所以,我们可以通过awk命令进行格式化输出,便于查看。(xx换成你要查看进程的id)
cat /proc/xx/net/snmp | awk "(f==0) {name=$1; i=2; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} (f==1){ i=2; while ( i<=NF){ printf "%s%s = %d ", name, n[i], $i; i++}; f=0} "
具体应用实例
下面是我的应用实例,我要监控的是摄像头,经过查看是udp的传输,需要监控udp的数据传输,然后我对查看指令略加修改,筛选了输出。InDatagrams 是保存的累计流量值,若判断到连续时间内没有增长,则可判定进程断流。
通过popen函数,执行cmd命令,获得输出,new_dataRecord 取得当次获得的数据值,last_dataRecord 保存上次的历史值。每次做差与特定阈值作比较,若流量小于阈值,则记为一次流量缺失,连续出现多次时,则可认为断流。
char buf[1024];
std::string cmd = "cat /proc/" + std::to_string(pid) + "/net/snmp | awk '(f==0) {name=$1; i=2; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} (f==1){ i=2; str1=\"Udp:\"; str2=\"InDatagrams\"; while (i<=NF){ if(name==str1&&n[i]==str2){ printf \"%d\\n\", $i; } i++}; f=0}'";
FILE* fp = popen(cmd.c_str(), "r");
if (fgets(buf, 1024, fp))
{
uint64_t new_dataRecord = std::atoll(buf);
if (new_dataRecord - last_dataRecord > c_flow_monitor_threshold)
flow_monitor_stat = 2;
else
flow_monitor_stat--;
if (flow_monitor_stat <= 0)
{
last_dataRecord = 0;
return false;
}
last_dataRecord = new_dataRecord;
}