ping
来源:互联网 发布:mips 64位 网络处理器 编辑:程序博客网 时间:2024/04/26 13:44
///unit.cpp/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.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;
}
//---------------------------------------------------------------------------
//////////////////////unit1.h///////////////////////////////////////////////////////
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#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
TMemo *Memo1;
TPanel *Panel1;
TLabel *Label1;
TLabel *Label2;
TLabel *Label3;
TEdit *Edit1;
TEdit *Edit2;
TEdit *Edit3;
TButton *Button1;
TButton *Button2;
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;//接收到的报文数目
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);
// User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
- ping .............
- ping
- ping
- ping
- ping
- ping
- Ping
- ping
- ping
- ping
- ping
- ping .
- ping
- ping
- ping
- ping ....
- ping
- PING
- EODA.For.Oracle.V1.5.0719
- web开发中的缓存问题的研究(三)
- 如何在 Visual C++.NET 2003 下编译eMule
- web开发中的缓存问题的研究(二)
- Cross site script
- ping
- 又完成两个功能
- web开发中的缓存问题的研究(一)
- 安装DEBIAN
- Javascript的变量作用域居然可以跨越多个函数!
- php access
- Debian M-Howto : 安装个人wiki [Dokuwiki 版本]
- 安装流量监控MRTG
- ADO与ADO.NET概述