您的位置:首页 > 其它

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

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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: