计算机网络课程设计ping工具Word文档下载推荐.docx
《计算机网络课程设计ping工具Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《计算机网络课程设计ping工具Word文档下载推荐.docx(21页珍藏版)》请在冰点文库上搜索。
![计算机网络课程设计ping工具Word文档下载推荐.docx](https://file1.bingdoc.com/fileroot1/2023-5/3/a6a94a9b-bada-4e5b-8f14-476f37d2ad0b/a6a94a9b-bada-4e5b-8f14-476f37d2ad0b1.gif)
1.2.1、设计基本思路
在PING的工作原理下,PING程序基于ICMP,使用ICMP的回送请求和回送应答来工作。
为了实现直接对IP和ICMP包进行操作,设计采用RAW模式的SOCKET编程,实现网络连通性的测试,探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接。
当传送IP数据包发生错误,ICMP协议将会把错误信息封包,然后传送回给主机。
PING程序是面向用户的应用程序,该程序使用ICMP的封装机制,通过IP协议来工作。
1.2.2、PING的工作原理
PING程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接。
ping使用的是ICMP协议,它发送ICMP回送请求消息给目的主机。
ICMP协议规定:
目的主机必须返回ICMP回送应答消息给源主机。
如果源主机在一定时间内收到应答,则认为主机可达。
ICMP协议通过IP协议发送的,IP协议是一种无连接的,不可靠的数据包协议。
因此,保证数据送达的工作应该由其他的模块来完成。
其中一个重要的模块就是ICMP(网络控制报文)协议。
当传送IP数据包发生错误--比如主机不可达,路由不可达等等,ICMP协议将会把错误信息封包,然后传送回给主机。
给主机一个处理错误的机会,这也就是为什么说建立在IP层以上的协议是可能做到安全的原因。
ICMP数据包由8bit的错误类型和8bit的代码和16bit的校验和组成。
而前16bit就组成了ICMP所要传递的信息。
PING利用ICMP协议包来侦测另一个主机是否可达。
原理是用类型码为0的ICMP发请求,受到请求的主机则用类型码为8的ICMP回应。
ping程序来计算间隔时间,并计算有多少个包被送达。
用户就可以判断网络大致的情况。
1.2.3、RAW模式的SOCKET编程
WindowsSockets规范以U.C.Berkeley大学BSDUNIX中流行的Socket接口为范例定义了一套MicorosoftWindows下网络编程接口。
它不仅包含了人们所熟悉的BerkeleySocket风格的库函数;
也包含了一组针对Windows的扩展库函数,以使程序员能充分地利用Windows消息驱动机制进行编程。
WindowsSockets规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。
此外,在一个特定版本Windows的基础上,WindowsSockets也定义了一个二进制接口(ABI),以此来保证应用WindowsSocketsAPI的应用程序能够在任何网络软件供应商的符合WindowsSockets协议的实现上工作。
因此这份规范定义了应用程序开发者能够使用,并且网络软件供应商能够实现的一套库函数调用和相关语义。
任何能够与WindowsSockets兼容实现协同工作的应用程序就被认为是具有WindowsSockets接口。
我们称这种应用程序为WindowsSockets应用程序。
WindowsSockets规范定义并记录了如何使用API与Internet协议族(IPS,通常我们指的是TCP/IP)连接,尤其要指出的是所有的WindowsSockets实现都支持流套接口和数据报套接口.
应用程序调用WindowsSockets的API实现相互之间的通讯。
WindowsSockets又利用下层的网络通讯协议功能和操作系统调用实现实际的通讯工作。
程序详细设计说明
<
1>
初始化winsock2网络环境
WSADATAwsa;
if(WSAStartup(MAKEWORD(2,2),&
wsa)!
=0)
{
cerr<
"
\n初始化WinSock2DLL失败\n"
<
errorcode:
<
WSAGetLastError()<
endl;
return-1;
}
2>
//将命令行参数转换为IP地址
u_longulDestIP=inet_addr(argv[2]);
if(ulDestIP==INADDR_NONE)
{
//转换不成功时按域名解析
hostent*pHostent=gethostbyname(argv[2]);
if(pHostent)
{
ulDestIP=(*(in_addr*)pHostent->
h_addr).s_addr;
//输出屏幕信息
cout<
\nping"
argv[2]<
inet_ntoa(*(in_addr*)(&
ulDestIP));
}
else//解析主机名失败
cerr<
\n解析主机名"
argv[2]<
"
失败!
'
\n'
errorcode:
WSACleanup();
return-1;
}
else
//输出屏幕信息
cout<
ping主机"
endl;
3>
填充目的Socket地址
sockaddr_indestSockAddr;
ZeroMemory(&
destSockAddr,sizeof(sockaddr_in));
destSockAddr.sin_family=AF_INET;
destSockAddr.sin_addr.s_addr=ulDestIP;
4>
创建RawSocket
SOCKETsockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
if(sockRaw==INVALID_SOCKET)
\n创建rawsocket失败\n"
;
WSACleanup();
5>
设置端口属性
intiTimeout=DEF_ICMP_TIMEOUT;
if(setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&
iTimeout,sizeof(iTimeout))==SOCKET_ERROR)
\n设置发送时间超时失败\n"
closesocket(sockRaw);
if(setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&
\n设置接收时间超时失败\n"
;
6>
创建ICPM包发送缓冲区和接收缓冲区
charIcmpSendBuf[sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE];
memset(IcmpSendBuf,0,sizeof(IcmpSendBuf));
charIcmpRecvBuf[MAX_ICMP_PACKET_SIZE];
memset(IcmpRecvBuf,0,sizeof(IcmpRecvBuf));
7>
填充待发送的ICMP包
ICMP_HEADER*pIcmpHeader=(ICMP_HEADER*)IcmpSendBuf;
pIcmpHeader->
type=ICMP_ECHO_REQUEST;
//类型为请求回显pIcmpHeader->
code=0;
//代码字段为0
pIcmpHeader->
id=(USHORT)GetCurrentProcessId();
//ID字段为当前进程号
USHORTusSeqNo=0;
//以默认大小填充数据字段
memset(IcmpSendBuf+sizeof(ICMP_HEADER),'
E'
DEF_ICMP_DATA_SIZE);
发送ICMP数据报
if(sendto(sockRaw,IcmpSendBuf,sizeof(IcmpSendBuf),0,
(sockaddr*)&
destSockAddr,sizeof(destSockAddr)==SOCKET_ERROR
//如果目的主机不可达则直接退出
if(WSAGetLastError()==WSAEHOSTUNREACH)
发送失败:
return0;
8>
接收ICMP数据报
while
(1)
{
iReadDataLen=recvfrom(sockRaw,IcmpRecvBuf,MAX_ICMP_PACKET_SIZE,0,(sockaddr*)&
from,&
iFromLen);
if(iReadDataLen!
=SOCKET_ERROR)//有数据包到达
{
if(DecodeIcmpResponse(IcmpRecvBuf,iReadDataLen,
stDecodeResult,ittl))
if(stDecodeResult.dwIPaddr.s_addr==destSockAddr.sin_addr.s_addr)
{
Recived++;
Replyfrom"
inet_ntoa(stDecodeResult.dwIPaddr);
stDecodeResult.dwRoundTripTime=GetTickCount()-stDecodeResult.dwRoundTripTime;
//统计传输时间
SumTripTime+=stDecodeResult.dwRoundTripTime;
if(Recived==1){MaxTripTime=MinTripTime=stDecodeResult.dwRoundTripTime;
}
else
if(stDecodeResult.dwRoundTripTime>
MaxTripTime)MaxTripTime=stDecodeResult.dwRoundTripTime;
if(stDecodeResult.dwRoundTripTime<
MinTripTime)MinTripTime=stDecodeResult.dwRoundTripTime;
//输出本次传输时间
if(stDecodeResult.dwRoundTripTime)
cout<
:
time="
stDecodeResult.dwRoundTripTime<
ms"
else
cout<
time"
1"
ms"
cout<
TTl="
int(ittl)<
break;
else
Requesttimedout."
elseif(WSAGetLastError()==WSAETIMEDOUT)//接收超时
break;
cerr<
\n接收数据失败!
\n"
<
closesocket(sockRaw);
WSACleanup();
return-1;
9>
定义头类型文件
#include"
StdAfx.h"
typedefstruct
{
unsignedcharhdr_len:
4;
//lengthoftheheader
unsignedcharversion:
//versionofIP
unsignedchartos;
//typeofservice
unsignedshorttotal_len;
//totallengthofthepacket
unsignedshortidentifier;
//uniqueidentifier
unsignedshortfrag_and_flags;
//flags
unsignedcharttl;
//timetolive
unsignedcharprotocol;
//protocol(TCP,UDPetc)
unsignedshortchecksum;
//IPchecksum
unsignedlongsourceIP;
//sourceIPaddress
unsignedlongdestIP;
//destinationIPaddress
}IP_HEADER;
//ICMP数据报头
BYTEtype;
//8位类型
BYTEcode;
//8位代码
USHORTcksum;
//16位校验和
USHORTid;
//16位标识符
USHORTseq;
//16位序列号
}ICMP_HEADER;
//解码结果
USHORTusSeqNo;
//包序列号
DWORDdwRoundTripTime;
//往返时间
in_addrdwIPaddr;
//对端IP地址
}DECODE_RESULT;
//线程参数
structThread_Param
charIPaddr1[20];
charIPaddr2[20];
};
typedefstructThread_ParamThread_Param;
typedefstructThread_Param*pThread_Param;
//ICMP类型字段
constBYTEICMP_ECHO_REQUEST=8;
//请求回显
constBYTEICMP_ECHO_REPLY=0;
//回显应答
constBYTEICMP_TIMEOUT=11;
//传输超时
constDWORDDEF_ICMP_TIMEOUT=50;
//默认超时时间,单位ms
constintDEF_ICMP_DATA_SIZE=32;
//默认ICMP数据部分长度
constintMAX_ICMP_PACKET_SIZE=1024;
//最大ICMP数据报的大小
constintDEF_MAX_HOP=30;
//最大跳站数
USHORTGenerateChecksum(USHORT*pBuf,intiSize);
BOOLDecodeIcmpResponse(char*pBuf,intiPacketSize,DECODE_RESULT&
stDecodeResult,unsignedchar&
ittl);
DWORDSingle_ThreadProc(LPVOIDlpParameter);
DWORDMulti_ThreadProc(LPVOIDlpParameter);
classPing
public:
Ping();
~Ping();
voidAction_Clear();
voidSetMainHwnd(HWNDhwnd);
voidStart();
voidScanSingleHost(char*IPaddr1,char*IPaddr2);
voidScanMultiHost(char*IPaddr1,char*IPaddr2);
private:
HWNDmain_hwnd;
protected:
10>
输出窗口图形化设计
StatusWindow:
StatusWindow()
nID=0;
num_parts=1;
hStatusWin=NULL;
BOOLStatusWindow:
CreateStatus(HWNDhwnd,intnum_parts,int*Width,intnID)
this->
nID=nID;
if(Width==NULL)
MessageBox(hwnd,TEXT("
宽度数组不能为空!
),TEXT("
提示"
),MB_ICONWARNING);
returnFALSE;
}
if(num_parts>
=1&
&
num_parts<
=255)
this->
num_parts=num_parts;
分栏数范围(1-255)!
hStatusWin=CreateStatusWindow(WS_CHILD|WS_VISIBLE,NULL,hwnd,nID);
//IDC_STATUS需要在resource.h里面自己定义
if(hStatusWin==NULL)
创建状态栏失败!
),MB_ICONERROR);
BOOLresult=SendMessage(hStatusWin,SB_SETPARTS,(WPARAM)num_parts,(LPARAM)Width);
if(result==FALSE)
设置分栏操作失败!
returnresult;
returnTRUE;
~StatusWindow()
InsertItem(HWNDhwnd,intIndex_part,char*contents)
if(Index_part<
0||Index_part>
num_parts)
状态栏索引错误!
if(contents==NULL)
内容不能为空!
状态栏句柄为空!
BOOLret=SendMessage(hStatusWin,SB_SETTEXT,(WPARAM)Index_part,(LPARAM)contents);
if(ret==FALSE)
状态栏插入文本操作失败!
returnret;
HWNDStatusWindow:
GethStatus()
returnhStatusWin;
使用说明结果分析
在VC中运行程序后会出现如下图所示,提示你输入IP
当要pin