分享
 
 
 

用VC++ 6.0制作网络自动测试程序

王朝c/c++·作者佚名  2006-01-06
窄屏简体版  字體: |||超大  

本报2000年11月27日第46期的应用编程中,登载了“用VC++6.0制作网络测试程序”一文。该文介绍的网络测试方法是通过调用WINDOWS目录下的PING.EXE命令来实现的。程序执行时,须用鼠标点中拓扑图某网络节点热区,并通过所运行PING.EXE命令的DOS窗口来观察测试结果。由于没有自动测试功能,所以使用不够方便。

由MICROSOFT公司开发的WINDOWS SOCKETS提供了WINDOWS环境下网络通讯的编程接口。在VC++6.0中,可以通过调用WINDOWS SOCKETS函数,采用原始套接字(RAW SOCKETS)类型和互连网控制消息协议(ICMP),来编制一个能实现PING功能的函数。通过定时调用该函数,就可实现网络的自动测试。若再加上语音报警功能,就是一个很实用的网络测试程序。本文拟介绍实现此功能的程序的制作方法。

为便于说明起见,我们还是按“用VC++6.0制作网络测试程序”一文介绍的方法,先做一个简单的网络测试程序(Netest)。注意,在制作Netest工程的STEP 4 OF 6时 ,要钩选WINDOWS SOCKETS选项。否则,在下面要编译AUTOP.CPP文件时,将会出错。在Netest工程编译成功后,再做以下几项工作:

一、增加AUTOP. CPP到工程文件中

在工程à添加工程à文件à将AUTOP.CPP添加到当前工程文件中(AUTOP.CPP的源码见下面第三节的内容所示,应事先将其COPY到当前工程的目录中)。

二、在工程中增加自动测试的有关菜单和函数

(1)在“用VC++6.0制作网络测试程序”一文介绍的Netest工程中,其Readinfo()函数的最后一条语句GlobalFree(hHost)释放了装载有初始化信息的内存,当随后调用PING.EXE时,问题不是很大。但若调用WINSOCK函数,内存中的初始化信息会被冲掉。所以须将该语句移到程序结束处再执行。可如下增加OnDestroy()函数:

在ClassWizard中,对应Class name=CNetestView, Object IDs= CNetestView,Message =WM_DESTROY,点击Add FunctionàOnDestroyàEdit Code,增加相应代码如下:

void CNtestView::OnDestroy()

{

CFormView::OnDestroy();

GlobalFree(hHost); //从Readinfo()移到此

for (int i=0; i<nodeNum; i++)

DeleteObject(lpHost[i].hrgn);

}

(2)增加自动测试菜单Autotest:在资源工作区,选中MENUàIDR_MAINFRAMEà点中空的菜单条à属性à令ID=ID_AUTOTEST,标题=Autotest。

在ClassWizard中,对应Class name=CNetestView,Object IDs=ID_AUTOTEST,Message =COMMAND,点击Add FunctionàOnAutotest àEdit Code,增加相应代码如下:

void CNtestView::OnAutotest()

{

SetTimer(1, 30000,NULL); //each 30s interupt 1 time.

Tc=20;

CWnd* pParent=GetParent();

CMenu * pMenu=pParent->GetMenu();

pMenu->EnableMenuItem(ID_AUTOPING,MF_BYCOMMAND| MF_DISABLED | MF_GRAYED);

pMenu->EnableMenuItem(ID_STOPAUTO,MF_ENABLED);

AfxGetMainWnd()->SendMessage (WM_TIMER,0, 0L);

}

其中SetTimer()将定时器设为每30秒中断一次。由Tc计算中断次数。余下几句条语句令Autotest菜单变灰,以免多次重入。最后一条语句使得鼠标点击Autotest菜单后,即转到OnTimer()函数开始自动测试。

(3)增加定时测试代码。在ClassWizard中,对应Class name=CNetestView的Message, 选中WM_TIMERàAdd FunctionàEdit Code,在OnTimer() 函数中增加如下代码:

void CNetestView::OnTimer(UINT nIDEvent)

{

if(Tc++<20) return;

KillTimer(1);

Tc=0;

BOOL bOK=TRUE;

InvalidateRect(NULL);

for(int ipT=0;ipT

{

if(Autotest(lpHost[ipT].nodeIP,3)==FALSE) {

CString strerr;

strerr.Format("err%d.wav",ipT+1);

sndPlaySound(strerr, SND_LOOP |SND_ASYNC );

HDC hdc= CreateDC("DISPLAY",0,0,0);

SelectObject(hdc,lpHost[ipT].hrgn);

InvertRgn(hdc,lpHost[ipT].hrgn);

DeleteDC(hdc);

bOK=FALSE;

}

else if(bOK) sndPlaySound("Bird0.wav", SND_ASYNC);

}

SetTimer(1, 30000,NULL);

CFormView::OnTimer(nIDEvent);

}

本程序设计为每10分钟对网络作一次自动测试。所以第一条语句须检查定时器中断是否已够20次(30秒*20=10分钟)。若够的话,就关断定时器,循环调用Autotest()对所有网络节点进行测试。若Autotest()的返回值为FALSE,说明该节点有问题,随即调用对应声波文件发出不停的报警声。在报警的同时,程序继续往下运行,作余下网络节点的测试。若所有节点均正常,则调用BIRD0.WAV声波文件发出动听的鸟鸣声。全部节点测试完后,才用SetTimer()再次启动定时器。

报警声波文件的制作,可在WINDOWS的附件à娱乐à录音机,通过麦克风录下报警语音。按照在INFO.INI文件中各节点的顺序,将语音文件分别存为ERR1.WAV,ERR2.WAV……。这样,网络节点的报警声就能和出错节点正确对应。

测试时,若有2个以上网络节点有问题,前一个出错节点只会报警一次,最后一个出错节点则会发出循环报警声。为了便于用户观察出错情况,用InvertRgn()来反相显示出错节点的区域。InvalidateRect(NULL)函数用来使屏幕刷新,以便下一次测试的观察。

三、AUTOP.CPP的源码及说明

AUTO.CPP的源码如下:

//#include 头文件略

. . . . . . . . . . .

typedef struct _ihdr {

BYTE i_type, i_code;

u_short i_cksum,i_id, i_seq;

}IcmpHeader;

struct sockaddr_in saDestAddr;

CString Messtr,Tmpstr;

u_short checksum(u_short *buffer, int size) {

. . . . . . .(略)

}

BOOL Autotest(char far * szDestHost,int Ktest)

{

WSADATA wsaData;

SOCKET sockRaw;

struct sockaddr_in dest,from;

char icmp_data[10], recvbuf[100];

unsigned int addr=0;

int fromlen = sizeof(from);

int timeout = 1000; //ms

WSAStartup(MAKEWORD(2,1),&wsaData) ;

sockRaw = socket (AF_INET,SOCK_RAW,IPPROTO_ICMP);

setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,

(char*)&timeout,sizeof(timeout) );

memset(&dest,0,sizeof(dest));

dest.sin_family = AF_INET;

dest.sin_addr.s_addr= inet_addr(szDestHost);

memset(icmp_data,0,sizeof(icmp_data)); //clear icmp_data.

((IcmpHeader*)icmp_data)->i_type = 8; //ICMP_ECHO

((IcmpHeader*)icmp_data)->i_code = 0;

((IcmpHeader*)icmp_data)->i_id = (u_short)GetCurrentProcessId();

((IcmpHeader*)icmp_data)->i_seq = 0;

for(int k=0; k

{

((IcmpHeader*)icmp_data)->i_cksum = 0;

((IcmpHeader*)icmp_data)->i_seq ++;

((IcmpHeader*)icmp_data)->i_cksum=checksum((u_short*)icmp_data,8);

sendto(sockRaw,icmp_data,8,0,(struct sockaddr*)&dest,sizeof(dest));

int bread=recvfrom(sockRaw,recvbuf,1024,0,(struct sockaddr*)&from,

&fromlen);

if (bread == SOCKET_ERROR){

if(k==Ktest-1) goto ERR1 ;

else continue; //try again(3 times)

}

}

return TRUE; //no erros.

ERR1:

closesocket (sockRaw);

sockRaw= INVALID_SOCKET;

WSACleanup();

return FALSE;

}

为简洁起见,源码中大部分的出错处理语句都删去了。整个函数执行的过程如下:

(1)用WSAStartup()函数初始化WINSOCK DLL。

(2)用socket()函数建立一个原始套接字sockRaw。

(3)用setsockopt()函数来设置套接字的选择项。这里用SO_RCVTIMEO参数来设置接收超时。超时值由timeout=1000设定超时最长时间为1秒钟。

(4)给被测节点的dest和Icmpheader结构变量赋值。其中szDestHost放被测节点的IP地址(点间隔格式),inet_addr()函数将一个点间隔的地址转换成4字节的地址;Icmpheader结构的i_type=8表示发送一个请求响应数据包(ICMP_ECHO),i_id为数据包的标识,i_cksum为数据包的校验和,i_seq用来为发送包计数。

(5)用sendto()函数向被测节点发送信息,用recvfrom()函数接收被测节点的应答信息。若在规定时间内(1秒)收不到应答信息,再连测2次。若3次的发送均收不到应答信息,可认为网络故障。Ktest的值决定对被测节点反复测试的次数。(当收到应答信息时,还认应检查应答信息内容正确后,才认为网络正常。本例略去这些检查似乎也无妨)。

(6)测试完一个节点后,用closesocket()函数关闭套接字,用WSAcCleanup()函数释放为应用程序分配的资源。

至此,就可以编译和执行程序,体会个中乐趣。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有