谁给个ping 工具的程序

hendyzou 2007-07-05 03:08:20
如题
...全文
219 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
LGBlueSky 2007-08-07
  • 打赏
  • 举报
回复
.h文件
//---------------------------------------------------------------------------

#ifndef UnitPingH
#define UnitPingH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <winsock2.h>

#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

#define ICMP_MIN 8 //ICMP报头的最小字节数
#define MAXIPHEADER 60 //IP数据报的最大字节数
#define MAXNUM 10 //定义发送的报文的次数数
// IP header
typedef struct tagIPHEADER {
unsigned char h_len:4; // length of the header
unsigned char version:4; // Version of IP
unsigned char tos; // Type of service
unsigned short total_len; // total length of the packet
unsigned short ident; // unique identifier
unsigned short frag_and_flags; // flags
unsigned char ttl;
unsigned char proto; // protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum

unsigned int sourceIP;
unsigned int destIP;

} IPHEADER;
// ICMP header
typedef struct tagICMPHEADER
{
BYTE i_type;
BYTE i_code;
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
ULONG timestamp; //时间戳
} ICMPHEADER;
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TMemo *Memo1;
TEdit *Edit1;
TLabel *Label1;
TLabel *Label2;
TEdit *Edit2;
TButton *Button1;
TButton *Button2;
TEdit *Edit3;
TLabel *Label3;
TTimer *Timer1;
void __fastcall Button2Click(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
private:
SOCKET SockRaw;//Socket对象
char* pICMPData;//指向ICMP数据缓冲区
char* pRecvBuf;//指向接收数据缓冲区
sockaddr_in saDest;//存储Ping的目的地址
int PacketSize;//数据长度
int SeqIndex;//报文序号
int RecvPack;//接收到的报文数目

private: // User declarations
void Ping();
void IniSocket();
void Fill_ICMP_Data(char *pICMPData, int nDataSize);
USHORT CheckSum(USHORT *DataBuffer, int Size);//校验和函数
//数据解码函数
bool Decode_Resp(char *Buffer, int Bytes, sockaddr_in *SocketFrom);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
LGBlueSky 2007-08-07
  • 打赏
  • 举报
回复
cpp文件
#include <vcl.h>
#pragma hdrstop

#include "UnitPing.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Edit1->Text="127.0.0.1";
Edit2->Text="64";
Edit3->Text="1000";
Memo1->Lines->Clear();
SeqIndex = 0;
RecvPack = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

IniSocket();//初始化/善后工作
Ping();//调用Ping函数
}
//---------------------------------------------------------------------------
void TForm1::Ping()//完成ping功能
{
struct hostent * hp;
char * strHost;//主机地址
int nDataSize;//ICMP数据包长度
int timeout;
unsigned int addr = 0;
unsigned int dw;

WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
Memo1->Lines->Add("无法建立WinSock,请检查是否缺少相关动态链接库");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
Memo1->Lines->Add("无法建立WinSock,请检查是否缺少相关动态链接库");
WSACleanup();
return;
}

IniSocket();
//建立一个用于收发ICMP报的socket对象
if (INVALID_SOCKET == (SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)))
{
Memo1->Lines->Add("无法建立socket对象");
return ;
}
timeout = Edit3->Text.ToInt();//设置最大等待时间
if ((SOCKET_ERROR == setsockopt(SockRaw, SOL_SOCKET, SO_RCVTIMEO,
(char*)&timeout, sizeof(timeout))) ||
(SOCKET_ERROR == setsockopt(SockRaw, SOL_SOCKET, SO_SNDTIMEO,
(char*)&timeout, sizeof(timeout))))
{
Memo1->Lines->Add("Socket错误");
return ;
}

memset(&saDest,0,sizeof(saDest));//初始化为0
//inet_addr()将点分地址转换为整数地址
strHost=Edit1->Text.c_str();
if (INADDR_NONE == (addr = inet_addr(strHost)))
{
//gethostbyname()解析域名地址
if (NULL == (hp = gethostbyname(strHost)))
{
Memo1->Lines->Add("地址有误");
return;
}
else
{
saDest.sin_family = hp->h_addrtype;
memcpy(&(saDest.sin_addr),hp->h_addr,hp->h_length);
}
}
else
{
saDest.sin_family = AF_INET;
saDest.sin_addr.s_addr = addr;
}
PacketSize=Edit2->Text.ToInt();
nDataSize = PacketSize + sizeof(ICMPHEADER);
pICMPData = new char[nDataSize];
pRecvBuf = new char[nDataSize + MAXIPHEADER];
memset(pICMPData, 0, nDataSize);//置0
Fill_ICMP_Data(pICMPData, nDataSize);//填充ICMP报文
SeqIndex = 0;//本报文序号
RecvPack = 0;//清空接收到报文数目
Timer1->Enabled=true;//定时器开始工作
}
//----------------------------------------------------------------------------
void TForm1::IniSocket()//完成初始化/善后工作
{
if (INVALID_SOCKET != SockRaw)
{
closesocket(SockRaw);
SockRaw = INVALID_SOCKET;
}
if (NULL != pICMPData)
{
delete pICMPData;
pICMPData = NULL;
}
if (NULL != pRecvBuf)
{
delete pRecvBuf;
pRecvBuf = NULL;
}
}
//----------------------------------------------------------------------------
void TForm1::Fill_ICMP_Data(char *pICMPData, int nDataSize)
{
ICMPHEADER *pICMPHdr;
char *pDataPart;
pICMPHdr = (ICMPHEADER*)pICMPData;
pICMPHdr->i_type = ICMP_ECHO;
pICMPHdr->i_code = 0;
pICMPHdr->i_id = (USHORT)GetCurrentProcessId();
pICMPHdr->i_seq = 0;
pDataPart = pICMPData + sizeof(ICMPHEADER);
memset(pDataPart, 'E', nDataSize - sizeof(ICMPHEADER));
}
//-------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//定时发出ICMP报文
int nError;
int nWrite, nRead;
sockaddr_in from;//定义远端的Socket链接地址
int nfromLen = sizeof(from);
int nDataSize = PacketSize + sizeof(ICMPHEADER);
//如果超过了定义的最大发送报文数目,就停止ping
if (SeqIndex>=MAXNUM)
{
int Lost;//报文丢失比率
Lost = (SeqIndex - RecvPack) * 100 / SeqIndex;
Memo1->Lines->Add("Lost= "+AnsiString(Lost)+"%");
Timer1->Enabled=false;
IniSocket();
return;
}
//如果没有超过定义的最大发送报文数,就继续ping
((ICMPHEADER*)pICMPData)->i_cksum = 0;
((ICMPHEADER*)pICMPData)->timestamp = GetTickCount();//时间戳
((ICMPHEADER*)pICMPData)->i_seq = 0xffff & (SeqIndex ++);//给报文编号
((ICMPHEADER*)pICMPData)->i_cksum = CheckSum((USHORT*)pICMPData,
nDataSize);//校验和

if (SOCKET_ERROR == (nWrite = sendto(SockRaw, pICMPData, nDataSize, 0,
(struct sockaddr*)&saDest, sizeof(saDest))))
{
if (WSAETIMEDOUT == (nError = WSAGetLastError()))
{
Memo1->Lines->Add("超时错误");
}
else
{
Memo1->Lines->Add("发送报文错误");
Timer1->Enabled=false;//停止发送报文
}
return;
}
if (SOCKET_ERROR == (nRead = recvfrom(SockRaw, pRecvBuf,
nDataSize + MAXIPHEADER, 0, (struct sockaddr*)&from, &nfromLen)))
{
if (WSAETIMEDOUT == (nError = WSAGetLastError()))
{
Memo1->Lines->Add("超时错误");
} else
{
Memo1->Lines->Add("接收数据错误");
Timer1->Enabled=false;//停止发送报文
}
return;
}
Decode_Resp(pRecvBuf, nRead, &from);
}
//---------------------------------------------------------------------------
USHORT TForm1::CheckSum(USHORT *DataBuffer, int Size)//校验和函数
{
unsigned long Sum = 0;
while (1 < Size)
{
Sum += *DataBuffer++;
Size -= sizeof(USHORT);
}
if (Size)
Sum += *(UCHAR*)DataBuffer;
Sum = (Sum >> 16) + (Sum & 0xffff);
Sum += (Sum >>16);
return (USHORT)(~Sum);
}
//---------------------------------------------------------------------------
bool TForm1::Decode_Resp(char *Buffer, int Bytes, sockaddr_in *SocketFrom)
{ //程序接收到的是一个IP报文,为了得到ICMP报文,还必须分解此IP报
IPHEADER *iphdr;
ICMPHEADER *icmphdr;
unsigned short iphdrlen;
iphdr = (IPHEADER *)Buffer;
AnsiString StrOfPing;
//iphdrlen是以byte为单位,而iphdr是32bit为单位
iphdrlen = iphdr->h_len << 2 ;
if ((iphdrlen + ICMP_MIN) > Bytes)
{
Memo1->Lines->Add("收到字节数目太少");
return false;
}
icmphdr = (ICMPHEADER*)(Buffer + iphdrlen);
if (ICMP_ECHOREPLY != icmphdr->i_type)
{
Memo1->Lines->Add("类型有错");
return false;
}
if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
{
Memo1->Lines->Add("不是本程序的数据报");
return false;
}
++ RecvPack;//报文正确,累加器加一
StrOfPing="Reply from "+ AnsiString(inet_ntoa(SocketFrom->sin_addr))
+":"+" Seq "+AnsiString(icmphdr->i_seq)
+" bytes="+AnsiString(Bytes)
+" times="+AnsiString(GetTickCount()-icmphdr->timestamp)+"ms"
+" TTL:"+ AnsiString(iphdr->ttl);
Memo1->Lines->Add(StrOfPing);
return true;
}
//-----------------------------------------------------------------------------
LGBlueSky 2007-08-07
  • 打赏
  • 举报
回复
cpp文件
#include <vcl.h>
#pragma hdrstop

#include "UnitPing.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Edit1->Text="127.0.0.1";
Edit2->Text="64";
Edit3->Text="1000";
Memo1->Lines->Clear();
SeqIndex = 0;
RecvPack = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

IniSocket();//初始化/善后工作
Ping();//调用Ping函数
}
//---------------------------------------------------------------------------
void TForm1::Ping()//完成ping功能
{
struct hostent * hp;
char * strHost;//主机地址
int nDataSize;//ICMP数据包长度
int timeout;
unsigned int addr = 0;
unsigned int dw;

WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
Memo1->Lines->Add("无法建立WinSock,请检查是否缺少相关动态链接库");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
Memo1->Lines->Add("无法建立WinSock,请检查是否缺少相关动态链接库");
WSACleanup();
return;
}

IniSocket();
//建立一个用于收发ICMP报的socket对象
if (INVALID_SOCKET == (SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)))
{
Memo1->Lines->Add("无法建立socket对象");
return ;
}
timeout = Edit3->Text.ToInt();//设置最大等待时间
if ((SOCKET_ERROR == setsockopt(SockRaw, SOL_SOCKET, SO_RCVTIMEO,
(char*)&timeout, sizeof(timeout))) ||
(SOCKET_ERROR == setsockopt(SockRaw, SOL_SOCKET, SO_SNDTIMEO,
(char*)&timeout, sizeof(timeout))))
{
Memo1->Lines->Add("Socket错误");
return ;
}

memset(&saDest,0,sizeof(saDest));//初始化为0
//inet_addr()将点分地址转换为整数地址
strHost=Edit1->Text.c_str();
if (INADDR_NONE == (addr = inet_addr(strHost)))
{
//gethostbyname()解析域名地址
if (NULL == (hp = gethostbyname(strHost)))
{
Memo1->Lines->Add("地址有误");
return;
}
else
{
saDest.sin_family = hp->h_addrtype;
memcpy(&(saDest.sin_addr),hp->h_addr,hp->h_length);
}
}
else
{
saDest.sin_family = AF_INET;
saDest.sin_addr.s_addr = addr;
}
PacketSize=Edit2->Text.ToInt();
nDataSize = PacketSize + sizeof(ICMPHEADER);
pICMPData = new char[nDataSize];
pRecvBuf = new char[nDataSize + MAXIPHEADER];
memset(pICMPData, 0, nDataSize);//置0
Fill_ICMP_Data(pICMPData, nDataSize);//填充ICMP报文
SeqIndex = 0;//本报文序号
RecvPack = 0;//清空接收到报文数目
Timer1->Enabled=true;//定时器开始工作
}
//----------------------------------------------------------------------------
void TForm1::IniSocket()//完成初始化/善后工作
{
if (INVALID_SOCKET != SockRaw)
{
closesocket(SockRaw);
SockRaw = INVALID_SOCKET;
}
if (NULL != pICMPData)
{
delete pICMPData;
pICMPData = NULL;
}
if (NULL != pRecvBuf)
{
delete pRecvBuf;
pRecvBuf = NULL;
}
}
//----------------------------------------------------------------------------
void TForm1::Fill_ICMP_Data(char *pICMPData, int nDataSize)
{
ICMPHEADER *pICMPHdr;
char *pDataPart;
pICMPHdr = (ICMPHEADER*)pICMPData;
pICMPHdr->i_type = ICMP_ECHO;
pICMPHdr->i_code = 0;
pICMPHdr->i_id = (USHORT)GetCurrentProcessId();
pICMPHdr->i_seq = 0;
pDataPart = pICMPData + sizeof(ICMPHEADER);
memset(pDataPart, 'E', nDataSize - sizeof(ICMPHEADER));
}
//-------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//定时发出ICMP报文
int nError;
int nWrite, nRead;
sockaddr_in from;//定义远端的Socket链接地址
int nfromLen = sizeof(from);
int nDataSize = PacketSize + sizeof(ICMPHEADER);
//如果超过了定义的最大发送报文数目,就停止ping
if (SeqIndex>=MAXNUM)
{
int Lost;//报文丢失比率
Lost = (SeqIndex - RecvPack) * 100 / SeqIndex;
Memo1->Lines->Add("Lost= "+AnsiString(Lost)+"%");
Timer1->Enabled=false;
IniSocket();
return;
}
//如果没有超过定义的最大发送报文数,就继续ping
((ICMPHEADER*)pICMPData)->i_cksum = 0;
((ICMPHEADER*)pICMPData)->timestamp = GetTickCount();//时间戳
((ICMPHEADER*)pICMPData)->i_seq = 0xffff & (SeqIndex ++);//给报文编号
((ICMPHEADER*)pICMPData)->i_cksum = CheckSum((USHORT*)pICMPData,
nDataSize);//校验和

if (SOCKET_ERROR == (nWrite = sendto(SockRaw, pICMPData, nDataSize, 0,
(struct sockaddr*)&saDest, sizeof(saDest))))
{
if (WSAETIMEDOUT == (nError = WSAGetLastError()))
{
Memo1->Lines->Add("超时错误");
}
else
{
Memo1->Lines->Add("发送报文错误");
Timer1->Enabled=false;//停止发送报文
}
return;
}
if (SOCKET_ERROR == (nRead = recvfrom(SockRaw, pRecvBuf,
nDataSize + MAXIPHEADER, 0, (struct sockaddr*)&from, &nfromLen)))
{
if (WSAETIMEDOUT == (nError = WSAGetLastError()))
{
Memo1->Lines->Add("超时错误");
} else
{
Memo1->Lines->Add("接收数据错误");
Timer1->Enabled=false;//停止发送报文
}
return;
}
Decode_Resp(pRecvBuf, nRead, &from);
}
//---------------------------------------------------------------------------
USHORT TForm1::CheckSum(USHORT *DataBuffer, int Size)//校验和函数
{
unsigned long Sum = 0;
while (1 < Size)
{
Sum += *DataBuffer++;
Size -= sizeof(USHORT);
}
if (Size)
Sum += *(UCHAR*)DataBuffer;
Sum = (Sum >> 16) + (Sum & 0xffff);
Sum += (Sum >>16);
return (USHORT)(~Sum);
}
//---------------------------------------------------------------------------
bool TForm1::Decode_Resp(char *Buffer, int Bytes, sockaddr_in *SocketFrom)
{ //程序接收到的是一个IP报文,为了得到ICMP报文,还必须分解此IP报
IPHEADER *iphdr;
ICMPHEADER *icmphdr;
unsigned short iphdrlen;
iphdr = (IPHEADER *)Buffer;
AnsiString StrOfPing;
//iphdrlen是以byte为单位,而iphdr是32bit为单位
iphdrlen = iphdr->h_len << 2 ;
if ((iphdrlen + ICMP_MIN) > Bytes)
{
Memo1->Lines->Add("收到字节数目太少");
return false;
}
icmphdr = (ICMPHEADER*)(Buffer + iphdrlen);
if (ICMP_ECHOREPLY != icmphdr->i_type)
{
Memo1->Lines->Add("类型有错");
return false;
}
if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
{
Memo1->Lines->Add("不是本程序的数据报");
return false;
}
++ RecvPack;//报文正确,累加器加一
StrOfPing="Reply from "+ AnsiString(inet_ntoa(SocketFrom->sin_addr))
+":"+" Seq "+AnsiString(icmphdr->i_seq)
+" bytes="+AnsiString(Bytes)
+" times="+AnsiString(GetTickCount()-icmphdr->timestamp)+"ms"
+" TTL:"+ AnsiString(iphdr->ttl);
Memo1->Lines->Add(StrOfPing);
return true;
}
//-----------------------------------------------------------------------------
Y___Y 2007-07-06
  • 打赏
  • 举报
回复
《Network Programming for Microsoft Windows 2nd》上有个例子,用原始套接字实现的
fjye 2007-07-06
  • 打赏
  • 举报
回复
用TIdIcmpClient实现

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdIcmpClient1->Host = txtHost->Text;
IdIcmpClient1->Ping();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdIcmpClient1Reply(TComponent *ASender,
const TReplyStatus &AReplyStatus)
{
AnsiString Info;

switch (AReplyStatus.ReplyStatusType)
{
case rsEcho:
PrintInfo(
Info.sprintf("Reply from %s: bytes=%d time=%dms TTL=%d MsgType=%d SequenceId=%d",
AReplyStatus.FromIpAddress, AReplyStatus.BytesReceived,
AReplyStatus.MsRoundTripTime, AReplyStatus.TimeToLive,
AReplyStatus.MsgType, AReplyStatus.SequenceId
)
);
break;
case rsError:
PrintInfo("Error.");
break;
case rsTimeOut:
PrintInfo("Request timed out.");
break;
case rsErrorUnreachable:
PrintInfo("Destination host unreachable.");
break;
case rsErrorTTLExceeded:
PrintInfo("Error TTL exceeded.");
break;
default:
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PrintInfo(AnsiString Info)
{
Memo1->Lines->Add(Info);
}
//---------------------------------------------------------------------------

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧