【VC++开源代码栏目提醒】:网学会员--在 VC++开源代码编辑为广大网友搜集整理了:使用ICMP实现路由跟踪 - 互联网绩等信息,祝愿广大网友取得需要的信息,参考学习。
使用ICMP实现路由跟踪 下载本文示例源
代码 代码运行效果图如下 摘要本文简单介绍了ICMP协议和一种利用ICMP在
VC下实现网络路由跟踪的方法并给出一了个详细的例子。
关键字ICMP路由跟踪Visual C6.0 一、概述 计算机在Internet中传递信息时必须要经过路由器进行网络路由才能找到目的主机把信息送到目的主机。
路由器中都有一张路由表表中保存了从本路由器到某一主机的路由信息路由器就是通过该路由表进行网络寻径的。
两台主机之间并没有一条固定的路径即路由表并不固定该路径随着网络的变动而作相应的变动因而我们并不能直接从某一主机上得到去往另一主机的路径要得到本机与网络上某台主机的网络路径就必须要进行路由跟踪。
本文将介绍一种实现路由跟踪的方法。
二、ICMP简介 ICMP即Internet控制报文协议是一种用于特殊用途的报文机制可以使互联网中的路由器或主机报告差错或提供有关意外情况的信息。
ICMP报文为两级封装ICMP报文放在IP数据报的数据部分IP数据报则放在帧的数据中进行网络传输如下图1所示。
ICMP报文与其他普通报文一样具有相同的路由选择并没有特殊的优先权和增加可靠性。
图1ICMP报文的封装 在ICMP包头中包含了三个字段1字节类型域、1字节
代码域、2字节校验和。
类型域表示了该报文的类型如回应请求报文数据报超时报文等
代码域表示了该类型的几种不同情况如当类型为11超时报文时
代码为0表示TTL超时为1表示片重组超时。
在实现本文中所述的功能时要发送回应请求报文类型为8过程如下源主机向目的主机发送一个类型为8的回应请求报文若目的站点收到回应请求报文则把报文IP包头部中的目的IP与源IP地址交换将类型8改为回应类型0计算出新的校验和再发往源主机。
若源主机收到了该回应报文则不但说明了目的主机可达而且说明目的主机与源主机之间的路由器工作正常源主机和目的主机的IP、ICMP软件运行正常。
但若在传输过程中了出现了某些问题如网络不通等导致数据被定向到一个无效的目的地这时相关路由器或目的主机将发回目的不可达报文类型为3并在
代码中说明该报文的具体情况是网络不可达还是主机不可达等。
若请求报文在传输过程中超时即TTL被减为0报文每经过一个路由器TTL都要减1则该路由器返回一个TTL超时报文类型为11报文IP头中源IP地址即为本路由器的IP地址。
三、路由跟踪的实现方法 路由跟踪的实现就是巧妙地利用了ICMP报文的TTL超时报文。
其实现过程如下源主机先向目的主机发送一个回应请求报文类型8TTL值设为1第一个路由器收到后将TTL减1这样TTL变为0分组被废除同时路由器向源主机发送一个TTL超时报文类型为11报文的IP包头中的源IP地址就是第一个路由器的地址源主机就可以通过对该报文进行分析得到第一个路由器的地址。
接着发送TTL等于2的报文得到第二个路由器地址再发TTL等于3的报文如此下去直到收到目的主机的回应应答报文类型为0或目的不可达报文类型为3或者到了最大跳数要检测路由器个数的最大值。
可以看到对TTL的设置是实现跟踪的关键使用函数setsockoptm_SockIPPROTO_IPIP_TTLLPSTRTTLsizeofint可以对其进行设置m_Sock是所创建的套接字IP_TTL说明是进行TTL设置TTL即是要设置的TTL值为一个整形数值。
其实现流程可用下图2表示 图2流程图 四、程序实现 本文所介绍的程序是使用了Visual C6.0编写其过程如下 1、创建一个新的基于对话框的AppWizard工程并命名为RouteTrace。
2、在stdafx.h中加入includewinsock2.h。
3、打开选择菜单Project-SettingALTF7进入Project Setting对话框在Link下的Object/library modules输入ws2_32.lib然后点OK。
4、自定义一个ICMP类。
点击菜单中的Insert-New Class进入New Class对话框在Class type中选择Generic Class在Name中输入类名CICMP然后点OK这样就新建了一个CICMP类。
5、将对话框设置成如图3所示的样子 图3程序界面 启动Class Wizard为各控件添加响应函数和关联变量控件对应的ID及响应函数或变量为 控件ID响应函数变量地址组合框IDC_COMBO CComboBox m_comb最大跳数编辑框IDC_MAXHOT int m_maxhot跟踪按钮IDC_TRACEOnTrace停止按钮IDC_STOPOnStop列表框IDC_LIST CListCtrl m_list五、添加
代码 在完成了对各控件的设置和类的添加以后就是对
代码的编写了这里给出了新建类CICMP和RouteTraceDlg.cpp的
代码详细
代码请参看源程序。
ICMP.cpp文件
代码 //ICMP.cppimplementation of the CICMP class.////////////////////////////////////////////////////////////////////////includestdafx.hincludeRouteTrace.hincludeICMP.hincludews2tcpip.h//实现IP_TTL设置的关键ifdef _DEBUGundef THIS_FILEstatic char THIS_FILE__FILE__define new DEBUG_NEWendif////////////////////////////////////////////////////////////////////////Construction/Destruction//////////////////////////////////////////////////////////////////////CICMPCICMPwinsock0m_pIpNULLm_pIcmpNULLm_pIpIP_HEADnew BYTEMAX_PACKETm_pIcmpICMP_HEADnew BYTEMAX_PACKETCICMPCICMPdelete m_pIpdelete m_pIcmpBOOL CICMPInitializeWSADATA wsadataifWSAStartupMAKEWORD21wsadataAfxMessageBoxWSAStartup初始化失败return FALSEwinsockWSASocketAF_INET//建立socket SOCK_RAWIPPROTO_ICMPNULL00ifwinsockAfxMessageBoxSocket创建失败return FALSEint timeout5000setsockoptwinsockSOL_SOCKETSO_RCVTIMEOchartimeout//设置接收超时sizeoftimeouttimeout5000setsockoptwinsockSOL_SOCKETSO_SNDTIMEOchartimeout//设置发送超时sizeoftimeoutreturn TRUEvoid CICMPUninitialize//释放SocketifwinsockclosesocketwinsockWSACleanupUSHORT CICMPCheckSumUSHORTbufferint size//计算校验和unsigned long cksum0whilesize 1cksumbuffersize-sizeofUSHORTifsizecksumUCHARbuffercksumcksum 16cksum0xffffcksumcksum 16returnUSHORTcksum//--发送ICMP回应请求报文---BOOL CICMPSendICMPPackcharpAddrsockaddr_in sockAddrmemsetvoidsockAddr0sizeofsockAddrsockAddr.sin_familyAF_INETsockAddr.sin_port0sockAddr.sin_addr.S_un.S_addrinet_addrpAddrreturn SendICMPPacksockAddrBOOL CICMPSendICMPPacksockaddr_inpAddr//填充ICMP数据各项int statecharp_datam_pIcmp-typeICMP_ECHOm_pIcmp-code0m_pIcmp-IDUSHORTGetCurrentProcessIdm_pIcmp-number0m_pIcmp-timeGetTickCountm_pIcmp-cksum0//填充数据p_datacharm_pIcmpsizeofICMP_HEADmemsetcharp_data0DEF_PACKET//校验和m_pIcmp-cksumCheckSumUSHORTm_pIcmpDEF_PACKETsizeofICMP_HEAD//发送数据statesendtowinsockcharm_pIcmpDEF_PACKETsizeofICMP_HEADNULLstruct sockaddrpAddrsizeofsockaddrifstateSOCKET_ERRORifGetLastErrorWSAETIMEDOUTm_strInfo连接超时发送else m_strInfo.Format出现未知发送错误return FALSEifstate DEF_PACKETm_strInfo发送数据错误return FALSEmemcpyvoidm_sockAddrvoidpAddrsizeofsockaddr_inreturn TRUE//--接收数据--BOOL CICMPRecvICMPPackint stateint lensizeofsockaddr_incharaddrstruct hostentlpHostentNULLaddrinet_ntoam_sockAddr.sin_addrstaterecvfromwinsockcharm_pIpMAX_PACKET0struct sockaddrm_sockAddrlenifstateSOCKET_ERRORifWSAGetLastErrorWSAETIMEDOUTm_strInfo接收超时路由跟踪失败routestate0RouteState路由跟踪失败else m_strInfo未知接收错误return FALSE//分析数据int ipheadlenipheadlenm_pIp-HeadLen4ifstateipheadlenMIN_PACKETm_strInfo目的地址的响应数据不正确return FALSEICMP_HEADp_icmprevp_icmprevICMP_HEADcharm_pIpipheadlenswitchp_icmprev-typecase ICMP_ECHOREPLY//收到正常回显m_strInfo.Format接收到sd字节响应数据响应时间dms.inet_ntoam_sockAddr.sin_addrlenGetTickCount-p_icmprev-timerouteaddraddrroutestate0RouteState到达目的主机return TRUEbreakcase ICMP_TTLOUT//TTL超时routeaddrinet_ntoam_sockAddr.sin_addrroutestate1RouteState测试到路由器return TRUEbreakcase ICMP_DESUNREACH//目的不可达m_strInfo目的不可达routestate0RouteState目的不可达return TRUEbreakdefaultroutestate0m_strInfo未知错误RouteState不明状态return TRUE//--设置TTL--int CICMPSetTTLint TTLint nRetsetsockoptwinsockIPPROTO_IPIP_TTLLPSTRTTLsizeofintifnRetSOCKET_ERRORCString ttlerrttlerr.Format设置TTL错误AfxMessageBoxttlerrreturn 0return 1 RouteTraceDlg.cpp文件
代码//RouteTraceDlg.cppimplementation file//includestdafx.hincludeRouteTrace.hincludeRouteTraceDlg.hincludeafxmt.hifdef _DEBUGdefine new DEBUG_NEWundef THIS_FILEstatic char THIS_FILE__FILE__endif///////////////////////////////////////////////////////////////////////////////CAboutDlg dialog used for App Aboutstruct SubThreadInfoCDialogpDialogCListCtrllistCStaticstateCString IPStrint MaxhotInfoCEvent eventStopRoute//---路由跟踪线程---UINT ThreadRouteLPVOID pParamSubThreadInfopInfoSubThreadInfopParamCRouteTraceDlgpThreadDlgCRouteTraceDlgpInfo-pDialogCICMP m_icmpCString IPStrpInfo-IPStrCString sTTLint nTtlm_icmp.InitializefornTtl1nTtlpInfo-MaxhotnTtlifm_icmp.SetTTLnTtl0return 0sTTL.FormatdnTtlifm_icmp.SendICMPPackcharLPCSTRIPStrm_icmp.RecvICMPPackint ipInfo-list-InsertItem0sTTLpInfo-list-SetItemTexti1m_icmp.routeaddrpInfo-list-SetItemTexti2m_icmp.RouteStatepInfo-state-SetWindowTextm_icmp.m_strInfoSleep100ifm_icmp.routestate0//收到非TTL超时报文则跳出循环breakifWaitForSingleObjecteventStopRoute.m_hObject0WAIT_OBJECT_0break//收到停止信号则跳出循环pThreadDlg-RouteflagTRUEreturn 0…//系统
代码BOOL CRouteTraceDlgOnInitDialogCDialogOnInitDialog…//系统
代码//TODOAdd extra initialization here m_list.InsertColumn0标号LVCFMT_CENTER600m_list.InsertColumn1路由器地址HDF_CENTER2000m_list.InsertColumn2状态HDF_CENTER1000ListView_SetExtendedListViewStyleExm_list.m_hWndLVS_EX_FULLROWSELECT0xFFFFFFFFreturn TRUE//return TRUE unless you set the focus to acontrol…//系统
代码void CRouteTraceDlgOnTraceCString strUpdateDataTRUECWndpWndpWndGetDlgItemIDC_COMBOpWnd-GetWindowTextstrifstr.IsEmptyMessageBox请输入地址pWnd-SetFocusreturnifm_comb.FindStringExact-1strCB_ERRm_comb.AddStringstrm_list.DeleteAllItemsifRouteflagRouteflagFALSEInfo.IPStrstrInfo.pDialogthisInfo.Maxhotm_maxhotInfo.listm_listInfo.statem_statectlAfxBeginThreadThreadRouteInfo//在线程中实现路由跟踪void CRouteTraceDlgOnStopifRouteflageventStopRoute.SetEvent//发出停止信号void CRouteTraceDlgOnDestroyCDialogOnDestroy//TODOAdd your message handler code here m_icmp.Uninitialize 六、结束语 本文所述程序在Windows 98下Visual C6.0中调试通过并在宽带网中测试成功。
读者可根据实际需要修改程序中的参数以实现更强大的功能比如可以把超时值设置成更合适的值或设置成可动态输入的形式示例程序请看本文所附源码也可以本人主页中下载。
七、参考文献 1.胡晓军、邓波、高宏伟编著Visual C高级开发范例解析2002.1电子工业出版社 2.周明天、汪文勇编著TCP/IP网络原理与技术1993.12清华大学出版社
上一篇:
简单手写体数字识别系统
下一篇:
第1章 现在完成时和现在完成进行时