1、课程设计Ping程序设计与实现课 程 设 计 课程名称_计算机网络_题目名称_Ping程序设计与实现学生学院_计算机学院_专业班级_08计科4班_ 学 号_ _ 2011 年 1 月 8 日一、 课程设计目的本次课程设计的目的旨在通过网络相关程序的编写,使我们能深入理解TCP/IP协议机制,以及初步掌握基于Winsocket的网络编程技术。同时巩固相关的理论知识,为以后程序开发打下良好而又坚实的基础。二、知识准备1、ICMP协议互联网控制信息协议(Internet CONTROL Message Protocol),用于错误报告和调试。该协议是TCP/IP协议集中的一个子协议,属于网络层协议,
2、主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。我们可以通过Ping命令发送ICMP回应请求消息并记录收到ICMP回应回复消息,通过这些消息来对网络或主机的故障提供参考依据。常见ICMP报文有响应请求报文,目标不可到达、源抑制和超时报文,此外还有时间戳报文。2、Ping工作原理 Ping的原理就是首先建立通道,然后发送包,对方接受后返回信息,这个包至少包括以下内容:发送的时候,包的内容包括对方的ip地址和自己的地址,还有序列数;回送的时候包括双方地址,还有时间等
3、,主要是接受方在都是在操作系统内核里做好的,时刻在监听。Ping程序生成一个icmp“回送请求”,将其发送给目的主机。通过检测是否可以收到目标主机的应答,便可以知道网络的连通性。(3) Tracert 工作原理透过向目标发送不同 IP 生存时间 (TTL) 值的ICMP回应数据包,Tracert 诊断程序确定到目标所采取的路由。要求路径上的每个路由器在转发数据包之前至少将数据包上的 TTL 递减 1。数据包上的 TTL 减为 0 时,路由器应该将“ICMP已超时”的消息发回源系统。Tracert 先发送 TTL 为 1 的响应数据包,并在随后的每次发送过程将 TTL 递增1,直到目标响应或 T
4、TL 达到最大值,从而确定路由。透过检查中间路由器发回的“ICMP已超时”的消息确定路由。三、界面设计及数据结构的说明1 、MFC界面设计建立流程步骤一:打开VC6.0,点击文件选项,在project选项卡中选择MFC Appwizard(exe),项目名称为ping。步骤二:在新窗口中选择窗口类型为基于对话框的类型。步骤三:设置界面选项步骤四:设置窗口类型步骤五:选择相应类,点击finish完成。 界面建立成功后添加相应按钮及功能模块。主界面设计如下:2、数据结构的定义及说明(1)定义IP头部typedef struct _IpHeader unsigned int HeaderLength
5、:4; / 头部长度 unsigned int Version:4; / IP版本号 unsigned char TypeOfService; / 服务类型 unsigned short TotalLength; / 收发包的总长度 unsigned short Identification; / 唯一校验符 unsigned short FragmentationFlags; / 标志位 unsigned char TTL; / 生存时间 unsigned char Protocol; / 协议类型 (TCP, UDP 等) unsigned short CheckSum; / IP头部校验
6、和unsigned int sourceIPAddress; / 源地址 unsigned int destIPAddress; / 目的地址 IpHeader;(2)定义ICMP头部typedef struct _IcmpHeader BYTE IcmpType; /icmp类型 BYTE IcmpCode; /编码类型 USHORT IcmpChecksum; /icmp校验和 USHORT IcmpId; USHORT IcmpSeq; /icmp序列号 ULONG IcmpTimestamp; / 头部无标准定义,但仍需保留 IcmpHeader;(3)CIcmp类class CIcm
7、p : public CSocketpublic: BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents); BOOL OpenNewSocket(HWND hWnd, unsigned int NotificationMessage, long NotifyEvents, int AFamily, int AType, int AProtocol); int CloseIcmpSocket(void); BOOL Connect(int ReceiveTimeout, int Sen
8、dTimeout); BOOL Connect(LPINT ReceiveTimeout, LPINT SendTimeout, int AFamily, int AType, int AProtocol); int SetTTL(int TTL); int SetAsynchNotification(HWND hWnd, unsigned int Message, long Events); int Receive(LPSTR pIcmpBuffer, int IcmpBufferSize); unsigned long GetIPAddress (LPSTR iHostName); int
9、 Ping (LPSTR pIcmpBuffer, int IcmpBufferSize); unsigned short IcmpChecksum(unsigned short FAR *lpBuf, int Len); void DisplayError(CString ErrorType, CString FunctionName);public: CIcmp(void); CIcmp(CIcmp ©); CIcmp(void);private:public: LPIcmpHeader pIcmpHeader; LPIpHeader pIpHeader; SOCKET icmpS
10、ocket; SOCKADDR_IN icmpSockAddr; SOCKADDR_IN rcvSockAddr; DWORD icmpRoundTripTime; DWORD icmpPingSentAt; DWORD icmpPingReceivedAt; int icmpRcvLen; int icmpHops; int icmpMaxHops; int icmpCurSeq; int icmpCurId; int icmpPingTimer; int icmpSocketError; int icmpSocketErrorMod; unsigned long icmpHostAddre
11、ss;protected:;typedef CIcmp FAR * LPIcmp;(4)CPingPlusDlg类class CPingPlusDlg : public CDialogenum ImageType Icon_Blank, Icon_BlueArrow;private: void StopTimer(); void StartTimer(); void ChangeIconState(void); BOOL InitSockets(); BOOL FetchWinsockSettings(); BOOL LoadRegValues(void); void SaveRegValue
12、s(); void SendPing(void); unsigned long HostIPAddress();void UpdateTrace ();void DisplayTrace(LPCSTR TripTimeMessage, LPCSTR IPAddressMessage, LPCSTR HostMessage);void EndTrace(void);void InitImageList(); int AddListColumn(int column, int lfmt, int lmaxwidth, LPSTR ltext, int lsubitem); void Display
13、BlankLine(void); void SetTraceSequence(int Seq, int FocusItem, ImageType FocusImage); void SetTraceFocus(int FocusItem, int FocusSubItem); void SetDisplayImage(int FocusItem, enum ImageType FocusImage); void TraceComment(CString Comment);public: CPingPlusDlg(CWnd* pParent = NULL); / 标准构造器 protected:
14、 HICON m_hIcon; LRESULT OnPINGAsynch(WPARAM wParam, LPARAM lParam); public: CIcmp PingSocket; / Icmp 对象 WSADATA wsaData; / Windows Socket 信息结构 CString LocalNameServer; CString LocalDomainName; / 域名 (从注册机构获取) CString DefHost; / 默认主机名 (从注册机构获取) char HostNameMAXHOSTNAME; / 将主机名加入到会话中去char CurrentHostNa
15、meMAXHOSTNAME; / 当前正在ping的主机 struct in_addr TraceTarget; / 操作路径终端 BOOL TimerActive; / TRUE = 计时器到时 unsigned long icmpIntervalCount; / 当前计时时间间距unsigned long icmpMaxIntervals; / 最大间距 char icmpBufferMAX_PACKET; / icmp操作的普通缓冲区LPSTR pIcmpBuffer; / icmp缓冲区的故障分析报告指向int icmpDataLen; / icmp发出信息的字节数 (不计算头部)in
16、t icmpPingTTL; / 路径操作所用到的ttl值BOOL icmpTracing;/ TRUE = 路径操作, FALSE = PING操作BOOL PingSent; / TRUE = 等待ECHO回复, FALSE = 忽略输入;四、程序主题功能设计模块1、调用ping模块void CPingPlusDlg:OnPingButton() IconState = 0; DisplayBlankLine (); icmpTracing = FALSE; icmpPingTTL = PingSocket.icmpMaxHops; /ping生存时间为最大icmp跳数PingSocket
17、.icmpCurSeq = 0;/当前icmp序列为0 SendPing ( );/开始执行ping2、初始化socketBOOL CPingPlusDlg: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); return FALSE; return TRUE;
18、3、获取winsocket设置信息BOOL CPingPlusDlg:FetchWinsockSettings() SysTCPIP STcpIp;if (!STcpIp.WinsockVersion(&wsaData) MessageBox (No valid winsock.dll detected, CPingPlusDlg:OnInitDialog, MB_OK|MB_SYSTEMMODAL); return FALSE; if (!STcpIp.GetLocalHostName (&m_LocalHost) gethostname(CurrentHostName, MAXHOSTNA
19、ME); else memcpy (CurrentHostName, m_LocalHost, m_LocalHost.GetLength(); CurrentHostNamem_LocalHost.GetLength() = 0; m_LocalHost = CurrentHostName; if (!STcpIp.GetDomainName(&LocalDomainName) LocalDomainName = ; m_LocalHost += . + LocalDomainName; memcpy (CurrentHostName, m_LocalHost, m_LocalHost.Ge
20、tLength(); CurrentHostNamem_LocalHost.GetLength() = 0;if (!STcpIp.GetNSName (&LocalNameServer) LocalNameServer = ;m_NameServer = Name Server: + LocalNameServer; SetDlgItemText (IDC_LocalHost, m_LocalHost); SetDlgItemText (IDC_NameServer, m_NameServer);LoadRegValues();SetDlgItemText (IDC_DEST, HostNa
21、me);return TRUE;4、发送ping信息void CPingPlusDlg:SendPing(void)PingSent = TRUE; PingSocket.icmpCurSeq+; PingSocket.icmpCurId = (USHORT)GetCurrentProcessId();PingSocket.icmpHostAddress = HostIPAddress(); if (PingSocket.icmpHostAddress = NULL) return; if (icmpTracing) icmpPingTTL+; if (PingSocket.SetTTL (i
22、cmpPingTTL) = 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_ad
23、dr = PingSocket.icmpHostAddress; PingSocket.icmpSockAddr.sin_port = 0; StartTimer(); if (PingSocket.Ping (pIcmpBuffer, icmpDataLen) = SOCKET_ERROR) PingSocket.DisplayError(Ping, CPingPlusDlg:SendPing);5、设置超时时间int CIcmp:SetTTL(int TTL)int Result;Result = setsockopt (icmpSocket, IPPROTO_IP, IP_TTL, (L
24、PSTR)&TTL, sizeof(int);if (Result = SOCKET_ERROR) icmpSocketErrorMod = 1; icmpSocketError = WSAGetLastError(); return Result;6、Ping函数int CIcmp:Ping (LPSTR pIcmpBuffer, int DataLen)int Result;int IcmpBufferSize = DataLen + IcmpHeaderLength;pIcmpHeader = (LPIcmpHeader)pIcmpBuffer;memset (pIcmpBuffer,
25、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 = IcmpChecks
26、um (USHORT FAR *)pIcmpBuffer, IcmpBufferSize);icmpPingSentAt = GetCurrentTime(); Result = sendto (icmpSocket, pIcmpBuffer, IcmpBufferSize, 0, (LPSOCKADDR)&icmpSockAddr, sizeof icmpSockAddr);if (Result = SOCKET_ERROR) icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; return Result;7、校验和函数u
27、nsigned short CIcmp:IcmpChecksum(unsigned short FAR *lpBuf, int Len) register long ChkSum = 0L; while (Len 1) ChkSum += *(lpBuf+); Len -= sizeof (USHORT); if (Len) ChkSum += *(UCHAR *)lpBuf; ChkSum = (ChkSum & 0xffff) + (ChkSum16); ChkSum += (ChkSum 16);#pragma warning(disable : 4244) return (ChkSum
28、);#pragma warning(default : 4244)8、Receive函数int CIcmp:Receive(LPSTR pIcmpBuffer, int IcmpBufferSize) LPSOCKADDR pRcvSockAddr = (LPSOCKADDR)&rcvSockAddr;int Result; int RcvIpHdrLen;icmpPingReceivedAt = GetTickCount();icmpCurId = 0; rcvSockAddr.sin_family = AF_INET; rcvSockAddr.sin_addr.s_addr = INADD
29、R_ANY; rcvSockAddr.sin_port = 0; RcvIpHdrLen = sizeof rcvSockAddr; Result = recvfrom (icmpSocket, pIcmpBuffer, IcmpBufferSize, 0, pRcvSockAddr, &RcvIpHdrLen); if (Result = SOCKET_ERROR) icmpSocketError = WSAGetLastError(); icmpSocketErrorMod = 1; DisplayError (Receive,CIcmp:Receive); return Result; icmpRcvLen = Result; pIpHeader = (LPIpHeader)pIcmpBuffer; RcvIpHdrLen = pIpHeader-HeaderLength * 4; if (Result RcvIpHdrLen + ICMP_MIN) MessageBox(NULL, Short message!, CIcmp:Receive, MB
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1