课程设计Ping程序设计与实现.docx
《课程设计Ping程序设计与实现.docx》由会员分享,可在线阅读,更多相关《课程设计Ping程序设计与实现.docx(19页珍藏版)》请在冰豆网上搜索。
课程设计Ping程序设计与实现
课程设计
课程名称____计算机网络_____
题目名称_Ping程序设计与实现
学生学院____计算机学院____
专业班级____08计科4班___
学号_______
2011年1月8日
一、课程设计目的
本次课程设计的目的旨在通过网络相关程序的编写,使我们能深入理解TCP/IP协议机制,以及初步掌握基于Winsocket的网络编程技术。
同时巩固相关的理论知识,为以后程序开发打下良好而又坚实的基础。
二、知识准备
1、ICMP协议
互联网控制信息协议(InternetCONTROLMessageProtocol),用于错误报告和调试。
该协议是TCP/IP协议集中的一个子协议,属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。
当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。
我们可以通过Ping命令发送ICMP回应请求消息并记录收到ICMP回应回复消息,通过这些消息来对网络或主机的故障提供参考依据。
常见ICMP报文有响应请求报文,目标不可到达、源抑制和超时报文,此外还有时间戳报文。
2、Ping工作原理
Ping的原理就是首先建立通道,然后发送包,对方接受后返回信息,这个包至少包括以下内容:
发送的时候,包的内容包括对方的ip地址和自己的地址,还有序列数;回送的时候包括双方地址,还有时间等,主要是接受方在都是在操作系统内核里做好的,时刻在监听。
Ping程序生成一个icmp“回送请求”,将其发送给目的主机。
通过检测是否可以收到目标主机的应答,便可以知道网络的连通性。
(3)Tracert工作原理
透过向目标发送不同IP生存时间(TTL)值的ICMP回应数据包,Tracert诊断程序确定到目标所采取的路由。
要求路径上的每个路由器在转发数据包之前至少将数据包上的TTL递减1。
数据包上的TTL减为0时,路由器应该将“ICMP已超时”的消息发回源系统。
Tracert先发送TTL为1的响应数据包,并在随后的每次发送过程将TTL递增1,直到目标响应或TTL达到最大值,从而确定路由。
透过检查中间路由器发回的“ICMP已超时”的消息确定路由。
三、界面设计及数据结构的说明
1、MFC界面设计建立流程
步骤一:
打开VC6.0,点击文件选项,在project选项卡中选择MFCAppwizard(exe),项目名称为ping。
步骤二:
在新窗口中选择窗口类型为基于对话框的类型。
步骤三:
设置界面选项
步骤四:
设置窗口类型
步骤五:
选择相应类,点击finish完成。
界面建立成功后添加相应按钮及功能模块。
主界面设计如下:
2、数据结构的定义及说明
(1)定义IP头部
typedefstruct_IpHeader
{
unsignedintHeaderLength:
4;//头部长度
unsignedintVersion:
4;//IP版本号
unsignedcharTypeOfService;//服务类型
unsignedshortTotalLength;//收发包的总长度
unsignedshortIdentification;//唯一校验符
unsignedshortFragmentationFlags;//标志位
unsignedcharTTL;//生存时间
unsignedcharProtocol;//协议类型(TCP,UDP等)
unsignedshortCheckSum;//IP头部校验和
unsignedintsourceIPAddress;//源地址
unsignedintdestIPAddress;//目的地址
}IpHeader;
(2)定义ICMP头部
typedefstruct_IcmpHeader
{
BYTEIcmpType;//icmp类型
BYTEIcmpCode;//编码类型
USHORTIcmpChecksum;//icmp校验和
USHORTIcmpId;
USHORTIcmpSeq;//icmp序列号
ULONGIcmpTimestamp;//头部无标准定义,但仍需保留
}IcmpHeader;
(3)CIcmp类
classCIcmp:
publicCSocket
{
public:
BOOLOpenNewSocket(HWNDhWnd,unsignedintNotificationMessage,longNotifyEvents);
BOOLOpenNewSocket(HWNDhWnd,unsignedintNotificationMessage,longNotifyEvents,intAFamily,intAType,intAProtocol);
intCloseIcmpSocket(void);
BOOLConnect(intReceiveTimeout,intSendTimeout);
BOOLConnect(LPINTReceiveTimeout,LPINTSendTimeout,intAFamily,intAType,intAProtocol);
intSetTTL(intTTL);
intSetAsynchNotification(HWNDhWnd,unsignedintMessage,longEvents);
intReceive(LPSTRpIcmpBuffer,intIcmpBufferSize);
unsignedlongGetIPAddress(LPSTRiHostName);
intPing(LPSTRpIcmpBuffer,intIcmpBufferSize);
unsignedshortIcmpChecksum(unsignedshortFAR*lpBuf,intLen);
voidDisplayError(CStringErrorType,CStringFunctionName);
public:
CIcmp(void);
CIcmp(CIcmp©);
~CIcmp(void);
private:
public:
LPIcmpHeaderpIcmpHeader;
LPIpHeaderpIpHeader;
SOCKETicmpSocket;
SOCKADDR_INicmpSockAddr;
SOCKADDR_INrcvSockAddr;
DWORDicmpRoundTripTime;
DWORDicmpPingSentAt;
DWORDicmpPingReceivedAt;
inticmpRcvLen;
inticmpHops;
inticmpMaxHops;
inticmpCurSeq;
inticmpCurId;
inticmpPingTimer;
inticmpSocketError;
inticmpSocketErrorMod;
unsignedlongicmpHostAddress;
protected:
};
typedefCIcmpFAR*LPIcmp;
(4)CPingPlusDlg类
classCPingPlusDlg:
publicCDialog
{
enumImageType
{
Icon_Blank,
Icon_BlueArrow
};
private:
voidStopTimer();
voidStartTimer();
voidChangeIconState(void);
BOOLInitSockets();
BOOLFetchWinsockSettings();
BOOLLoadRegValues(void);
voidSaveRegValues();
voidSendPing(void);
unsignedlongHostIPAddress();
voidUpdateTrace();
voidDisplayTrace(LPCSTRTripTimeMessage,LPCSTRIPAddressMessage,LPCSTRHostMessage);
voidEndTrace(void);
voidInitImageList();
intAddListColumn(intcolumn,intlfmt,intlmaxwidth,LPSTRltext,intlsubitem);
voidDisplayBlankLine(void);
voidSetTraceSequence(intSeq,intFocusItem,ImageTypeFocusImage);
voidSetTraceFocus(intFocusItem,intFocusSubItem);
voidSetDisplayImage(intFocusItem,enumImageTypeFocusImage);
voidTraceComment(CStringComment);
public:
CPingPlusDlg(CWnd*pParent=NULL);//标准构造器
protected:
HICONm_hIcon;
LRESULTOnPINGAsynch(WPARAMwParam,LPARAMlParam);
public:
CIcmpPingSocket;//Icmp对象
WSADATAwsaData;//WindowsSocket信息结构
CStringLocalNameServer;
CStringLocalDomainName;//域名(从注册机构获取)
CStringDefHost;//默认主机名(从注册机构获取)
charHostName[MAXHOSTNAME];//将主机名加入到会话中去
charCurrentHostName[MAXHOSTNAME];//当前正在ping的主机
structin_addrTraceTarget;//操作路径终端
BOOLTimerActive;//TRUE=计时器到时
unsignedlongicmpIntervalCount;//当前计时时间间距
unsignedlongicmpMaxIntervals;//最大间距
charicmpBuffer[MAX_PACKET];//icmp操作的普通缓冲区
LPSTRpIcmpBuffer;//icmp缓冲区的故障分析报告指向
inticmpDataLen;//icmp发出信息的字节数(不计算头部)
inticmpPingTTL;//路径操作所用到的ttl值
BOOLicmpTracing;//TRUE=路径操作,FALSE=PING操作
BOOLPingSent;//TRUE=等待ECHO回复,FALSE=忽略输入
};
四、程序主题功能设计模块
1、调用ping模块
voidCPingPlusDlg:
:
OnPingButton()
{
IconState=0;
DisplayBlankLine();
icmpTracing=FALSE;
icmpPingTTL=PingSocket.icmpMaxHops;//ping生存时间为最大icmp跳数
PingSocket.icmpCurSeq=0;//当前icmp序列为0
SendPing();//开始执行ping
}
2、初始化socket
BOOLCPingPlusDlg:
:
InitSockets()
{
if(!
PingSocket.OpenNewSocket(GetSafeHwnd(),
WSA_PING_ASYNC,
FD_READ|FD_WRITE,
AF_INET,
SOCK_RAW,
IPPROTO_ICMP))
{
PingSocket.DisplayError("WSA_PING_ASYNC",
"CPingPlusDlg:
:
InitSockets");
returnFALSE;
}
returnTRUE;
}
3、获取winsocket设置信息
BOOLCPingPlusDlg:
:
FetchWinsockSettings()
{
SysTCPIPSTcpIp;
if(!
STcpIp.WinsockVersion(&wsaData))
{
MessageBox("Novalidwinsock.dlldetected",
"CPingPlusDlg:
:
OnInitDialog",
MB_OK|MB_SYSTEMMODAL);
returnFALSE;
}
if(!
STcpIp.GetLocalHostName(&m_LocalHost))
{
gethostname(CurrentHostName,MAXHOSTNAME);
}
else
{
memcpy(CurrentHostName,m_LocalHost,m_LocalHost.GetLength());
CurrentHostName[m_LocalHost.GetLength()]=0;
}
m_LocalHost=CurrentHostName;
if(!
STcpIp.GetDomainName(&LocalDomainName))
LocalDomainName="";
m_LocalHost+="."+LocalDomainName;
memcpy(CurrentHostName,m_LocalHost,m_LocalHost.GetLength());
CurrentHostName[m_LocalHost.GetLength()]=0;
if(!
STcpIp.GetNSName(&LocalNameServer))
LocalNameServer="";
m_NameServer="NameServer:
"+LocalNameServer;
SetDlgItemText(IDC_LocalHost,m_LocalHost);
SetDlgItemText(IDC_NameServer,m_NameServer);
LoadRegValues();
SetDlgItemText(IDC_DEST,HostName);
returnTRUE;
}
4、发送ping信息
voidCPingPlusDlg:
:
SendPing(void)
{
PingSent=TRUE;
PingSocket.icmpCurSeq++;
PingSocket.icmpCurId=(USHORT)GetCurrentProcessId();
PingSocket.icmpHostAddress=HostIPAddress();
if(PingSocket.icmpHostAddress==NULL)
return;
if(icmpTracing)
{
icmpPingTTL++;}
if(PingSocket.SetTTL(icmpPingTTL)==SOCKET_ERROR)
{PingSocket.DisplayError("setsocket(TTL)",
"CPingPlusDlg:
:
SendPing");
return;}
Sleep(100);//用蓝色箭头显示序列号及相应信息
SetTraceSequence(PingSocket.icmpCurSeq,
m_TraceList.GetItemCount(),
Icon_BlueArrow);
PingSocket.icmpSockAddr.sin_family=PF_INET;
PingSocket.icmpSockAddr.sin_addr.s_addr=PingSocket.icmpHostAddress;
PingSocket.icmpSockAddr.sin_port=0;
StartTimer();
if(PingSocket.Ping(pIcmpBuffer,icmpDataLen)==SOCKET_ERROR)
PingSocket.DisplayError("Ping","CPingPlusDlg:
:
SendPing");
}
5、设置超时时间
intCIcmp:
:
SetTTL(intTTL)
{
intResult;
Result=setsockopt(icmpSocket,IPPROTO_IP,IP_TTL,(LPSTR)&TTL,sizeof(int));
if(Result==SOCKET_ERROR)
{
icmpSocketErrorMod=1;
icmpSocketError=WSAGetLastError();}
returnResult;}
6、Ping函数
intCIcmp:
:
Ping(LPSTRpIcmpBuffer,intDataLen)
{
intResult;
intIcmpBufferSize=DataLen+IcmpHeaderLength;
pIcmpHeader=(LPIcmpHeader)pIcmpBuffer;
memset(pIcmpBuffer,'E',IcmpBufferSize);
memset(pIcmpHeader,0,IcmpHeaderLength);
pIcmpHeader->IcmpType=ICMP_ECHO;
pIcmpHeader->IcmpCode=0;
pIcmpHeader->IcmpChecksum=0;
pIcmpHeader->IcmpId=icmpCurId;
pIcmpHeader->IcmpSeq=icmpCurSeq;
pIcmpHeader->IcmpTimestamp=GetCurrentTime();
pIcmpHeader->IcmpChecksum=IcmpChecksum((USHORTFAR*)pIcmpBuffer,
IcmpBufferSize);
icmpPingSentAt=GetCurrentTime();
Result=sendto(icmpSocket,
pIcmpBuffer,
IcmpBufferSize,
0,
(LPSOCKADDR)&icmpSockAddr,
sizeoficmpSockAddr);
if(Result==SOCKET_ERROR)
{icmpSocketError=WSAGetLastError();
icmpSocketErrorMod=1;}
returnResult;}
7、校验和函数
unsignedshortCIcmp:
:
IcmpChecksum(unsignedshortFAR*lpBuf,intLen)
{
registerlongChkSum=0L;
while(Len>1)
{ChkSum+=*(lpBuf++);
Len-=sizeof(USHORT);}
if(Len)
ChkSum+=*(UCHAR*)lpBuf;
ChkSum=(ChkSum&0xffff)+(ChkSum>>16);
ChkSum+=(ChkSum>>16);
#pragmawarning(disable:
4244)
return(~ChkSum);
#pragmawarning(default:
4244)
}
8、Receive函数
intCIcmp:
:
Receive(LPSTRpIcmpBuffer,intIcmpBufferSize)
{
LPSOCKADDRpRcvSockAddr=(LPSOCKADDR)&rcvSockAddr;
intResult;
intRcvIpHdrLen;
icmpPingReceivedAt=GetTickCount();
icmpCurId=0;
rcvSockAddr.sin_family=AF_INET;
rcvSockAddr.sin_addr.s_addr=INADDR_ANY;
rcvSockAddr.sin_port=0;
RcvIpHdrLen=sizeofrcvSockAddr;
Result=recvfrom(icmpSocket,
pIcmpBuffer,
IcmpBufferSize,
0,
pRcvSockAddr,
&RcvIpHdrLen);
if(Result==SOCKET_ERROR)
{icmpSocketError=WSAGetLastError();
icmpSocketErrorMod=1;
DisplayError("Receive","CIcmp:
:
Receive");
returnResult;}
icmpRcvLen=Result;
pIpHeader=(LPIpHeader)pIcmpBuffer;
RcvIpHdrLen=pIpHeader->HeaderLength*4;
if(Result{
MessageBox(NULL,
"Shortmessage!
",
"CIcmp:
:
Receive",
MB