数据流量监测工具[视频会议][源玛共享]

  最近视频会议的一个模块总是有点不对劲,从网络接收的数据到缓冲并转发到网络的过程中发现数据流不正常,为了便于调试并清楚到底有多少数据收到并以多少速率转发到网络,决定写一个可以监测数据流量的工具。感觉这个工具在查看多路多点位置的数据流非常好用。推荐一下,希望大家多提意见。不明白的,请多提问题哦。

NOTE:这段代码在cygwin下调试过,结果看最后。本人的真正开发环境是vxworks下,所以在下面的代码中也附带了vxworks的相应部分。

1. 单通道版本

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

/* 工具功能 : 测试流媒体数据流经模块内部
  * 各个点的流量统计信息,用于软件问题的诊断调试
  * 工具功能 :在需要监测的位置添加一段监测 代码(见DEMO)
  * 然后调用PacketPrint() 并传入监测时间,过一段时间就可以看到结果。 
  * 工具DEMO    : 
  * {
  *  static short nCallerID = INVALID_VALUE;
  *
  *  PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  * }

*/

#define CYGWIN_ENVIRONMENT   /*定义测试环境*/

#define INVALID_VALUE   -1
#define MAX_CALLERS    30   /*流量统计监测点的最大数目*/
#define MAX_FUNC_NAME_LEN  100  /*监测点调用函数的函数名最大长度*/
#define MAX_MONITOR_SECONDS  99  /*流量统计时间,单位为秒*/
#define MAX_PACKET_NUM   60*(MAX_MONITOR_SECONDS+1)/*最大测试包数*/ 

#define TRUE      1 
#define FALSE     0

typedef struct _TagCallerInfo

 char   pFuncName[MAX_FUNC_NAME_LEN]; /*调用函数的函数名,caller名称*/
 char   nFuncLen;/*调用函数的函数名实际长度*/  
 short  nLine;/*调用函数的调用点位置*/  

}TCallerInfo;

typedef struct _TagPacketInfo

 int    nPackets;  /*监测点流经总包数*/ 
 int    nPacketRate; /*监测点流量*/ 
 int    nPrevPackets; /*该点上一次监测的累计包数*/  
 long   nPrevTicks;  /*该点上一次监测的累计时间*/
 int    nInterval;  /*前后两次监测的时间跨度*/
 
}TPacketInfo;


static TCallerInfo  g_tCaller[MAX_CALLERS];
static TPacketInfo g_tPacket[MAX_CALLERS];
static int    g_nCallers   = 0;

void PacketStat(char* pFuncName,short nLine,short* pCallerID);
void PacketPrint(int nInterval/*second*/);

void hello(void);
void world(void);
void delay(void);

#ifdef CYGWIN_ENVIRONMENT   
int main(int argc, char *argv[])
{
 int i;

 hello();/*监测1,caller 为hello*/
 world();/*监测2,caller 为world*/
}
#else/*vxworks*/
void usrAppInit (void)
{
#ifdef USER_APPL_INIT
 USER_APPL_INIT;
#endif

     /* add application specific code here */
  hello();/*监测1,caller 为hello*/
 world();/*监测2,caller 为world*/
}

#endif

void hello(void)
{
 int i,j;

 for (i = 0 ; i < MAX_PACKET_NUM; i++)
 {
#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/   
  delay();
#else/*vxworks*/
  taskDelay(3);/*模拟20 包每秒的速率*/     
#endif

  /*----- 包率监测点具体位置---*/
  {
   static short nCallerID = INVALID_VALUE;

   PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  }
  /*--------------------------------------*/  
 }
}

void world(void)
{
 int i,j;

 for (i = 0 ; i < MAX_PACKET_NUM; i++)
 {
#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/   
  delay();
#else/*vxworks*/
  taskDelay(3);/*模拟20 包每秒的速率*/     
#endif

  /*----- 包率监测点具体位置---*/
  {
   static short nCallerID = INVALID_VALUE;

   PacketStat(__FUNCTION__,__LINE__,&nCallerID);
  }
  /*--------------------------------------*/  
 }
}

#ifdef CYGWIN_ENVIRONMENT   
void delay(void)
{
 int i=10000;

 while(i-->0)/*延时10000 cycles,任意定义,可以是其它值*/
  ;
}
#endif

void PacketStat(char* pFuncName,short nLine,short* pCallerID)
{
 int    nCaller    = 0;
 long   nCurrTicks   = 0; 
 static int   bInitialized   = FALSE;
 TCallerInfo*  ptCaller   = NULL;
 TPacketInfo* ptPacket  = NULL;
 
 if (NULL == pFuncName || NULL == pCallerID)
 {
  printf("invalid function name and pos pointer!");
  return;
 }

 if (!bInitialized)
 { /*第一次要初始化*/
  memset(&g_tCaller[0],0,sizeof(TCallerInfo)*MAX_CALLERS);
  memset(&g_tPacket[0],0,sizeof(TPacketInfo)*MAX_CALLERS);
  bInitialized = TRUE;
 }
  
 if (INVALID_VALUE == *pCallerID)
 { /*如果是某监测点第一次调用该函数*/
  nCaller    = g_nCallers++; 
  ptCaller    = &g_tCaller[nCaller];
  
  ptCaller->nFuncLen = strlen(pFuncName);

  if (ptCaller->nFuncLen>MAX_FUNC_NAME_LEN)
  {
   printf("too long function name!/n");  
   return;
  }

  ptCaller->nFuncLen  = sprintf(ptCaller->pFuncName,"%s",pFuncName);

  ptCaller->nLine  = nLine;
  *pCallerID    = nCaller;/*返回当前监测点的ID,以备后用*/

#ifdef CYGWIN_ENVIRONMENT/*cygwin 下测试代码*/
  PacketPrint(MAX_MONITOR_SECONDS);
#endif
 }
 else
 {
  nCaller = *pCallerID;
 }

 ptCaller  = &g_tCaller[nCaller];
 ptPacket  = &g_tPacket[nCaller];

 /*等待用户设置检测时间*/
 if (ptPacket->nInterval <1)
 { 
  return;
 }

 if (nCaller >= 0 && nCaller<MAX_CALLERS)
 {
  ptPacket->nPackets++;

#ifdef CYGWIN_ENVIRONMENT/*设置包率为1 个tick 一个包的情况,测试代码的正确性*/ 
  nCurrTicks = ptPacket->nPackets;
#else
  nCurrTicks = tickGet();
#endif
  if (0 == ptPacket->nPrevTicks)
  {
   ptPacket->nPrevPackets  = ptPacket->nPackets;
   ptPacket->nPrevTicks   = nCurrTicks;
  }
  else
  {
   if (nCurrTicks-ptPacket->nPrevTicks >= ptPacket->nInterval*60)
   {
    ptPacket->nPacketRate = 60*(ptPacket->nPackets - ptPacket->nPrevPackets)
     /(nCurrTicks - ptPacket->nPrevTicks);

    printf("%s %5d:packets %d,rate %d p/s/n",ptCaller->pFuncName,
     ptCaller->nLine,ptPacket->nPackets,ptPacket->nPacketRate);

    ptPacket->nPrevTicks  = 0;
    ptPacket->nInterval  = 0;
   }
  }
 }
}

void PacketPrint(int nInterval/*second*/)
{
 int nCaller;

 for (nCaller = 0; nCaller < g_nCallers; nCaller++)
 {    
  g_tPacket[nCaller].nInterval = nInterval;
 }
}
 

 

 2. 多通道改进版本

 #ifdef PACKET_RATE_MONITOR
#include <string.h>
#define MAX_CALLERS    30   /*流量统计监测点的最大数目*/
#define MAX_CHANNELS    64   /*每个监测点支持通道的最大数目*/

#define MAX_FUNC_NAME_LEN  30  /*监测点调用函数的函数名最大长度*/
#define MAX_HINT_INFO_LEN   80  /*监测点调用函数的函数名最大长度*/
#define MAX_MONITOR_SECONDS  99  /*流量统计时间,单位为秒*/
#define MAX_PACKET_NUM   60*(MAX_MONITOR_SECONDS+1)/*最大测试包数*/ 

typedef struct _TagCallerInfo

 NW_CHAR pchFuncName[MAX_FUNC_NAME_LEN]; /*调用函数的函数名,caller名称*/
 NW_CHAR  nFuncLen;/*调用函数的函数名实际长度*/  
 NW_SHORT nLine;/*调用函数的调用点位置*/  

}TCallerInfo;

typedef struct _TagPacketInfo

 NW_INT32  nPackets[MAX_CHANNELS];  /*监测点流经总包数*/ 
 NW_INT32  nPacketRate[MAX_CHANNELS]; /*监测点流量*/ 
 NW_INT32 nPrevPackets[MAX_CHANNELS];/*该点上一次监测的累计包数*/  
 NW_INT32 nPrevTicks[MAX_CHANNELS]; /*该点上一次监测的累计时间*/
 NW_INT32  nInterval[MAX_CHANNELS];     /*前后两次监测的时间跨度*/
 
}TPacketInfo;


static TCallerInfo  g_tCaller[MAX_CALLERS];
static TPacketInfo g_tPacket[MAX_CALLERS];
static NW_INT32 g_nCallers = 0;

void PacketRatePrint(int nInterval/*second*/);

void PacketRateStat(NW_CHAR* pchFuncName,NW_SHORT nLine,NW_SHORT* pCallerID,NW_SHORT nChannelID)
{
 NW_INT32   nCaller    = 0;
 NW_INT32  nCurrTicks   = 0; 
 static NW_BOOL  bInitialized   = FALSE;
 TCallerInfo*   ptCaller   = NULL;
 TPacketInfo*  ptPacket  = NULL;
 
 if (NULL == pchFuncName || NULL == pCallerID)
 {
  printf("invalid function name and pos pointer!");
  return;
 }

 if (nChannelID < 0 || nChannelID >= MAX_CHANNELS)
 {
  printf("invalid channel id %d!",nChannelID);
  return;
 } 

 if (!bInitialized)
 { /*第一次要初始化*/
  memset(&g_tCaller[0],0,sizeof(TCallerInfo)*MAX_CALLERS);
  memset(&g_tPacket[0],0,sizeof(TPacketInfo)*MAX_CALLERS);
  bInitialized = TRUE;
 }
  
 if (INVALID_VALUE == *pCallerID)
 { /*如果是某监测点第一次调用该函数*/
  nCaller     = g_nCallers++; 
  ptCaller     = &g_tCaller[nCaller];
  
  ptCaller->nFuncLen = strlen(pchFuncName);

  if (ptCaller->nFuncLen>MAX_FUNC_NAME_LEN)
  {
   printf("too long function name!/n");  
   return;
  }

  ptCaller->nFuncLen  = sprintf(ptCaller->pchFuncName,"%s",pchFuncName);
  ptCaller->nLine  = nLine;
  *pCallerID    = nCaller;/*返回当前监测点的ID,以备后用*/
 }
 else
 {
  nCaller = *pCallerID;
 }

 ptCaller  = &g_tCaller[nCaller];
 ptPacket  = &g_tPacket[nCaller];

 /*等待用户设置检测时间*/
 if (ptPacket->nInterval[nChannelID] <1)
 { 
  return;
 }

 if (nCaller >= 0 && nCaller<MAX_CALLERS)
 {
  ptPacket->nPackets[nChannelID]++;

  nCurrTicks = tickGet();

  if (0 == ptPacket->nPrevTicks[nChannelID])
  {
   ptPacket->nPrevPackets[nChannelID]  = ptPacket->nPackets[nChannelID];
   ptPacket->nPrevTicks[nChannelID]   = nCurrTicks;
  }
  else
  {
   if (nCurrTicks-ptPacket->nPrevTicks[nChannelID] >= ptPacket->nInterval[nChannelID]*60)
   {
    ptPacket->nPacketRate[nChannelID] = 60*(ptPacket->nPackets[nChannelID] - ptPacket->nPrevPackets[nChannelID])
     /(nCurrTicks - ptPacket->nPrevTicks[nChannelID]);

    logMsg("%s %5d,channel %d:rate %d p/s,packets %d./n",ptCaller->pchFuncName,
     ptCaller->nLine,nChannelID,ptPacket->nPacketRate[nChannelID],ptPacket->nPackets[nChannelID]);

    ptPacket->nPrevTicks[nChannelID]  = 0;
    ptPacket->nInterval[nChannelID]  = 0;
   }
  }
 }
}

void PacketRatePrint(int nInterval/*second*/)
{
 NW_INT32 nCaller;
 NW_INT32 nChannel;
 
 for (nCaller = 0; nCaller < g_nCallers; nCaller++)
 { 
  for (nChannel = 0; nChannel < MAX_CHANNELS; nChannel++)
  {
   g_tPacket[nCaller].nInterval[nChannel] = nInterval;
  }
 }
}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值