cb中如何实现ping的功能

flingdragon 2002-11-20 09:11:52
我希望实现类似ping的功能,可以知道服务器与客户端的网络连接情况。
...全文
217 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
cuptbluesky 2003-03-01
  • 打赏
  • 举报
回复
gz
kk_liwei 2003-02-28
  • 打赏
  • 举报
回复
mark!
我不懂电脑 2003-02-27
  • 打赏
  • 举报
回复
用IDICMPClient组件很容易呀。
NowCan 2003-02-27
  • 打赏
  • 举报
回复
呵呵,这么多的ping,小弟再来一个。这个ping可以记录9个路由。

http://vip.6to23.com/NowCan1/tech/ping.htm
pepsi1980 2003-02-26
  • 打赏
  • 举报
回复
c++builder6安装目录下example下面有一个PINGGUI,就是啦,升级吧.......
playguy 2003-02-25
  • 打赏
  • 举报
回复
可以去这里看一看,有完整的解决方案,绝对实用:
http://www.aslike.net
l_clove 2003-01-21
  • 打赏
  • 举报
回复
一段代码,ping
typedef struct _ihdr
{
BYTE i_type; //类型:8--请求回送,0--请求回送回应
BYTE i_code; //代码 0
USHORT i_cksum; //校验和
USHORT i_id; //ID号,协议中无具体定义,一般填写进程ID
USHORT i_seq; //序列号
//上面为真实的头
//数据部分
ULONG timestamp;
} IcmpHeader;
void fill_icmp_data(char * icmp_data,int datasize); //填充包
USHORT checksum(USHORT * buffer,int size); //计算校验和

void __fastcall TForm1::Button1Click(TObject *Sender)
{
WSADATA WSAData;
SOCKET sockRAW;

//初始化
if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)
{
ShowMessage("Socket初始化失败!");
ShowMessage("错误信息:"+WSAGetLastError());
return;
}

//版本支持
if(WSAData.wVersion<0x0200)
{
ShowMessage("你的系统的Socket版本太低!");
WSACleanup();
return;
}

//建立socket描述符
if((sockRAW=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,0))==0)
{
ShowMessage("创建socket描述符失败!");
ShowMessage("错误信息:"+WSAGetLastError());
WSACleanup();
return;
}

//设置超时选项
int rcvTimeout=1000; //接收
if((setsockopt(sockRAW,SOL_SOCKET,SO_RCVTIMEO,(char *)&rcvTimeout,sizeof(rcvTimeout)))!=0)
{
ShowMessage("选项设置失败!");
ShowMessage("错误信息:"+WSAGetLastError());
closesocket(sockRAW);
WSACleanup();
return;
}

int sndTimeout=1000; //发送
if((setsockopt(sockRAW,SOL_SOCKET,SO_SNDTIMEO,(char *)&sndTimeout,sizeof(sndTimeout)))!=0)
{
ShowMessage("选项设置失败!");
ShowMessage("错误信息:"+WSAGetLastError());
closesocket(sockRAW);
WSACleanup();
return;
}

sockaddr_in sourc;
memset(&sourc,0,sizeof(sourc));
sourc.sin_family=AF_INET;
sourc.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if((bind(sockRAW,(sockaddr *)&sourc,sizeof(sourc)))==SOCKET_ERROR)
{
ShowMessage("地址绑定错误!");
closesocket(sockRAW);
WSACleanup();
return;
}

//地址转换
sockaddr_in dest;
memset(&dest,0,sizeof(dest));
dest.sin_family=AF_INET;
dest.sin_addr.S_un.S_addr=inet_addr(Edit1->Text.c_str());

//包大小
int datasize=32+sizeof(IcmpHeader);

//内存分配
char * icmp_data=(char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,1024);
char * recvbuf=(char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,1024);
if(icmp_data==NULL||recvbuf==NULL)
{
ShowMessage("内存分配错误!");
closesocket(sockRAW);
WSACleanup();
return;
}
memset(icmp_data,0,1024);



for(int i=0;i<5;i++)
{
fill_icmp_data(icmp_data,datasize);
((IcmpHeader *)icmp_data)->i_seq=i; //序列号
((IcmpHeader *)icmp_data)->i_cksum=checksum((USHORT *)icmp_data,datasize);
int bwrote=sendto(sockRAW,icmp_data,datasize,0,(struct sockaddr *)&dest,sizeof(dest));
if(bwrote==datasize) ShowMessage("OK,发送成功!");
else ShowMessage("Sorry,发送失败!");
}

closesocket(sockRAW);
WSACleanup();
}
//---------------------------------------------------------------------------
void fill_icmp_data(char * icmp_data,int datasize)
{
IcmpHeader * icmp_hdr=(IcmpHeader *)icmp_data;
char * datapart;
icmp_hdr->i_type=8; //类型:请求回送包
icmp_hdr->i_code=0; //代码:0
icmp_hdr->i_id=(USHORT)GetCurrentProcessId(); //进程ID作为包的ID
icmp_hdr->i_cksum=0; //校验和
icmp_hdr->i_seq=0; //序列号
icmp_hdr->timestamp=GetTickCount();
datapart=icmp_data+sizeof(IcmpHeader);
memset(datapart,'E',datasize-sizeof(IcmpHeader));
}

USHORT checksum(USHORT * buffer,int size)
{
unsigned long cksum=0;

while(size >1)
{
cksum+=*buffer++;
size -=sizeof(unsigned short);
}
if(size)
cksum += *(unsigned char*)buffer;
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (unsigned short)(~cksum);
}
yuyulily 2002-12-03
  • 打赏
  • 举报
回复
给你篇文章:
在Windows系统中,我们经常用Ping.exe来测试网络的连通性。

  Ping的实现过程很简单,该命令将引发IP层发送一个简单的IP包,一般是32字节。而目的方收到这个包后,将源地址和目的地址变换一下,重新发送这个包即可,当然还要加一些超时机制。

  其实,我们也可用C++ Builder NetMaster中的NMEcho控件来实现网络连接检测功能。

  首先定义以下控件:

  三个Edit控件:一个用于接收远程主机的IP地址或域名,一个用于接收用户设置的超时机制的时间,一个用于设置端口号。

  两个RichEdit控件:一个用于给远程主机发送信息,一个用于接收来自远程主机的信息。

  两个CheckBox控件:用于用户是否自己设定端口号。

  一个Button控件:用于执行测试。

  一个StatusBar控件:用于显示应用程序的状态。

  程序实现代码如下:

  void __fastcall TForm1::Button1Click(TObject Sender)

  { //设置NMEcho控件的标准TCP/IP属性

   NMEcho1->Host=Edit1->Text ;

   NMEcho1->TimeOut=StrToInt(Edit2->Text) ;

   if(CheckBox1->Checked)

     NMEcho1->Port=StrToInt(Edit3->Text);

   else

     NMEcho1->Port=7;

  //TCP/IP中Echo的默认端口号

  NMEcho1->ReportLevel=Status_Basic;

   NMEcho1->Connect(); //建立连接

   RichEdit2->Clear ();

   for(int i=0;i<RichEdit1->Lines->Count;i++)

  //RichEdit1用于给远程主机发送信息

  RichEdit2->Text=RichEdit2->Text +NMEcho1->Echo(RichEdit1->Lines->

  Strings[i]);

   NMEcho1->Disconnect ();

  }

  注意:在调用NMEcho控件的Connect()方法时,应该确保在接收数据之前连接已经建立。

  当调用Connect()方法后,如果用户输入的是域地址而不是IP地址,且域名服务器成功地解析了这个域名,将触发控件的OnHostResoved事件,在此事件的处理中,我们将解析成功的消息在状态栏中显示给用户。具体实现代码如下:

  void __fastcall TForm1::NMEcho1HostResolved(TComponent Sender)

  {

   StatusBar1->Panels->Items[0]->Text="Host Resolved!";    

  }

  如果用户输入的远程主机不正确,将触发控件的OnInvalidHost事件,在此事件的处理中,弹出对话框要求用户重新输入远程主机的IP地址或域名地址,然后试图与服务器重建连接。具体代码如下:

  void __fastcall TForm1::NMEcho1InvalidHost(bool &&Handled)

  {

   AnsiString s;

   if(InputQuery("Invailid host!","Specify a new host:",s))

   {

     NMEcho1->Host=s;

     Handled=true;

   }    

  }

  建立连接后,将触发控件的OnConnect事件,在此事件的处理中,我们将连接成功的消息在状态栏中显示给用户。具体实现代码如下:

  void __fastcall TForm1::NMEcho1Connect(TObject Sender)

  {

   StatusBar1->Panels->Items[0]->Text="Echo has connected host!";

    }

  如果在调用Connect()方法后,在超时时间仍然没有与服务器连接,将触发控件的OnConnectFailed事件,在此事件的处理中,我们将连接失败的消息显示给用户。具体实现代码如下:

  void __fastcall TForm1::NMEcho1ConnectionFailed(TObject Sender)

  {

  ShowMessage("Connection failed!");    

  }

  除了NMEcho控件可以实现以上功能外,NetMaster的NMDayTime、NMTime这两个控件也能实现。方法与NMEcho控件一样,区别是NMDayTime和NMTime这两个控件不用首先调用Connect()方法,它们与服务器的连接是在使用DayTimeStr、TimeStr属性时自动进行的。


invalid 2002-12-03
  • 打赏
  • 举报
回复
作个Ping的FAQ吧。我也来一段。我的一个网络监控的源代码。
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <inifiles.hpp>

#include "Unit1.h"
#pragma package(smart_init)
#pragma link "trayicon"
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
First = true;
FirstStart = true;
CurrentStatus = false;
RunStatus = false;
LastStatus = false;
if (FileExists(ExtractFilePath(Application->ExeName) + "history.dat"))
{
cbHosts->Items->LoadFromFile(ExtractFilePath(Application->ExeName) + "history.dat");
}

TIniFile *pIniFile=new TIniFile(ExtractFilePath(Application->ExeName)+"set.ini");

editInterval->Text = IntToStr(pIniFile->ReadString("Config","CheckIntelval","5").ToIntDef(5));
cbHosts->Text = pIniFile->ReadString("Config","MonitorAddress","");
cbAllReply->Checked = pIniFile->ReadBool("Config","ShowAllReply",false);
cbShowPrompt->Checked = pIniFile->ReadBool("Config","ShowPrompt",true);
cbAutoStart->Checked = pIniFile->ReadBool("Config","AutoStart",false);
cbAutoMin->Checked = pIniFile->ReadBool("Config","AutoMin",false);
delete pIniFile;

LONG dwStyle = GetWindowLong(editInterval->Handle, GWL_STYLE);
SetWindowLong(editInterval->Handle, GWL_STYLE, dwStyle | ES_NUMBER);

LogFileTime = TDateTime((int)Date());
LogFile = ExtractFilePath(Application->ExeName)+"Monitor"+Date().FormatString("YYYYMMDD")+".txt";
if(FileExists(LogFile))
{
Memo1->Lines->LoadFromFile(LogFile);
}
Msg("启动程序!");
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(btnRun->Caption == "停止")
{
btnRunClick(NULL);
}
Msg("关闭程序!");
Memo1->Lines->SaveToFile(LogFile);

TIniFile *pIniFile=new TIniFile(ExtractFilePath(Application->ExeName)+"set.ini");

pIniFile->WriteString("Config","CheckIntelval",editInterval->Text);
pIniFile->WriteString("Config","MonitorAddress",cbHosts->Text);
pIniFile->WriteBool("Config","ShowAllReply",cbAllReply->Checked);
pIniFile->WriteBool("Config","ShowPrompt",cbShowPrompt->Checked);
pIniFile->WriteBool("Config","AutoStart",cbAutoStart->Checked);
pIniFile->WriteBool("Config","AutoMin",cbAutoMin->Checked);
delete pIniFile;

cbHosts->Items->SaveToFile(ExtractFilePath(Application->ExeName) + "history.dat");
}

void __fastcall TForm1::btnRunClick(TObject *Sender)
{
if(btnRun->Caption == "开始")
{
int iInterval = editInterval->Text.ToIntDef(5);
if(cbHosts->Text.Trim().IsEmpty())
{
MessageBox(Handle,"未指定主机地址!","错误",MB_ICONWARNING|MB_OK|MB_SETFOREGROUND);
return;
}
if (cbHosts->Items->IndexOf(cbHosts->Text) == -1)
cbHosts->Items->Add(cbHosts->Text);

if(iInterval < 1)
{
iInterval = 5;
editInterval->Text = IntToStr(iInterval);
}
IdIcmpClient1->Host = cbHosts->Text;
Timer1->Interval = iInterval*1000;
IdIcmpClient1->ReceiveTimeout = 1000;
btnRun->Caption = "停止";
Msg("---------------------------------------------------------------------------");
Msg("开始监控->地址:"+IdIcmpClient1->Host+" 循环周期:"+IntToStr(iInterval)+"秒!");

LastStatus = true;
CurrentStatus = true;
RunStatus = true;
}
else
{
btnRun->Caption = "开始";
TrayIcon1->Hint = Application->Title;
Msg("停止监控!");
RunStatus = false;
}
}

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled = false;
if(FirstStart)
{
FirstStart = false;
if(cbAutoMin->Checked)
{
// Application->Minimize();
TrayIcon1->Minimize();
}
if(cbAutoStart->Checked)
{
btnRunClick(this);
}
Timer1->Enabled = true;
return;
}
if(RunStatus)
{
int i;

IdIcmpClient1->ReceiveTimeout = 1000;
try
{
IdIcmpClient1->Ping();
}
catch(Exception &e)
{
CurrentStatus = false;
if(First || LastStatus != CurrentStatus || cbAllReply->Checked)
{
SB1->Panels->Items[0]->Text = "中断";
TrayIcon1->IconIndex = 2;
TrayIcon1->Hint = "到"+IdIcmpClient1->Host+"连接中断!";
if(First || LastStatus != CurrentStatus)
{
ShowPromptWindow();
}
First = false;
LastStatus = CurrentStatus;
Msg("异常 ★★★ "+e.Message);
}
}
}
Timer1->Enabled = true;
}

void __fastcall TForm1::IdIcmpClient1Reply(TComponent *ASender,
const TReplyStatus &AReplyStatus)
{
AnsiString sTime, result[5],asMsg;

// TODO: Check for error on ping reply (ReplyStatus->MsgType?)
if (AReplyStatus.ReplyStatusType != rsEcho)
{
/* rsEcho - An Echo was received.
rsError - An error has occurred.
rsTimeOut - Timeout occurred before a response was received.
rsErrorUnreachable - The address for the ICMP message is not available.
rsErrorTTLExceeded - Time-To-Live exceeded for an ICMP response.
*/
CurrentStatus = false;
TrayIcon1->IconIndex = 2;
TrayIcon1->Hint = "到"+IdIcmpClient1->Host+"连接中断!";
}
else
{
CurrentStatus = true;
TrayIcon1->IconIndex = 1;
TrayIcon1->Hint = "到"+IdIcmpClient1->Host+"连接通畅!";
}
if(AReplyStatus.MsRoundTripTime == 0)
{
sTime = "<1";
}
else
{
sTime = "=";
}
result[0] = IntToStr(AReplyStatus.BytesReceived);
result[1] = AReplyStatus.FromIpAddress;
result[2] = IntToStr((int)AReplyStatus.SequenceId);
result[3] = IntToStr((int)AReplyStatus.TimeToLive);
result[4] = sTime;
result[5] = IntToStr(AReplyStatus.MsRoundTripTime);
asMsg = "Reply:"+(result[0] + " bytes from " + result[1] +
": icmp_seq=" + result[2] + " ttl=" + result[3] +
" time" + result[4] + result[5] + " ms");

if(First || LastStatus != CurrentStatus || cbAllReply->Checked)
{
First = false;
if(First || LastStatus != CurrentStatus)
{
ShowPromptWindow();
}
LastStatus = CurrentStatus;
if(!CurrentStatus)
{
SB1->Panels->Items[0]->Text = "中断";
Msg("中断 ★★★ "+asMsg);
}
else
{
SB1->Panels->Items[0]->Text = "通畅";
Msg("通畅 ☆☆☆ "+asMsg);
}
}
SB1->Panels->Items[1]->Text = Now().FormatString("YYYY-MM-DD hh:mm:ss->")+asMsg;
}

void __fastcall TForm1::btnExitClick(TObject *Sender)
{
Close();
}

void __fastcall TForm1::Msg(AnsiString asMsg)
{ Memo1->Lines->Add(Now().FormatString("YYYY-MM-DD hh:mm:ss->") + asMsg);
}
tccsdn 2002-12-03
  • 打赏
  • 举报
回复
unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TLabel *Label1;
TEdit *Edit1;
TButton *Button1;
TMemo *Memo1;
TCheckBox *CheckBox1;
TEdit *Edit2;
TLabel *Label2;
TButton *Button2;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations

typedef struct _iphdr
{
unsigned int h_len:4;
unsigned int version:4;
unsigned char tos;
unsigned short totl_len;
unsigned short ident;
unsigned short frag_and_flags;
unsigned char tt1;
unsigned char proto;
unsigned short checksum;

unsigned int sourceIP;
unsigned int destIP;
}IpHeader;

typedef struct _ipmphdr
{
BYTE i_type;
BYTE i_code;
USHORT i_cksum;
USHORT i_ip;
USHORT i_seq;
ULONG timestamp;
}IcmpHeader;

typedef struct _ipoptionhdr
{
unsigned char code;
unsigned char len;
unsigned char ptr;
unsigned long addr[9];
}IpOptionHeader;

bool bRecordRoute;
int datasize;
char *IpDest;
char szTemp[80];

void __fastcall FillIcmpData(char *icmp_data,int datasize);
USHORT __fastcall checksum(USHORT *buffer,int size);
void __fastcall DecodeIpOptions(char *buff,int bytes);
void __fastcall DecodeICMPHeader(char *buff,int bytes,struct sockaddr_in *from);
void __fastcall ValidataArgs();

public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
tccsdn 2002-12-03
  • 打赏
  • 举报
回复

void __fastcall TForm1::Button1Click(TObject *Sender)
{
WSADATA wsaData; //建立WSADATA结构的一个对象
SOCKET sockRaw=INVALID_SOCKET;
struct sockaddr_in dest,
from;
int bread,
fromlen=sizeof(from),
timeout=10,
ret;
char *icmp_data=NULL,
*recvbuff=NULL;
// unsigned int addr=0;
USHORT seq_no=0;
struct hostent *hp=NULL;
IpOptionHeader ipopt;

if(WSAStartup((WORD)((1<<8)|1),&wsaData))
{
MessageBox(NULL,"初始化动态链接库WSOCK32.DLL错误!","错误",MB_OK);
exit(EXIT_FAILURE);

//EXIT_FAILURE: 异常退出一个过程
//EXIT_EXIT_SUCCESS:正常退出一个过程
}
if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0)
{
Application->MessageBox( "WSAStartup() faild:"+GetLastError(),
Application->Title.c_str(),MB_OK);
}
ValidataArgs(); //初始化IP地址,数据包的大小,是否路由

//建立SOCK_RAW类型的原始套接字
//WINDOS98中WSASocket函数连接不过
//sockRaw=WSASocket( AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,
// WSA_FLAG_OVERLAPPED);
sockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(sockRaw==INVALID_SOCKET)
{
sprintf(szTemp,"建立SOCKET失败!错误代码:%d",GetLastError());
Application->MessageBox(szTemp,"错误",MB_OK);
}

//判断是否路由选项的处理
if(bRecordRoute)
{
ZeroMemory(&ipopt, sizeof(ipopt)); //申请一段无类型的内存空间
ipopt.code=IP_RECORD_ROUTE; //Record Route option=0x7
ipopt.ptr=4; //指向第一个地址的偏移量
ipopt.len=39; //IP选项头的长度

ret=setsockopt(sockRaw,IPPROTO_IP,IP_OPTIONS,(char *)&ipopt,sizeof(ipopt));
if(ret==SOCKET_ERROR)
{
sprintf(szTemp,"调用setsockopt(IP_OPTIONS)失败!错误代码:%d.",WSAGetLastError());
Application->MessageBox(szTemp,"错误",MB_OK);
exit(EXIT_FAILURE);
}
}

bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
if(bread==SOCKET_ERROR)
{
sprintf(szTemp,"调用setsockopt(SO_RCVTIMEO)失败!错误代码:%d.",WSAGetLastError());
Application->MessageBox(szTemp,"错误",MB_OK);
exit(EXIT_FAILURE);
}
memset(&dest, 0, sizeof(dest)); //把dest的内容全部为0;

dest.sin_family=AF_INET;
if((dest.sin_addr.S_un.S_addr=inet_addr(IpDest))==INADDR_NONE)
{
if((hp==gethostbyname(IpDest)!=NULL))
{
memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
dest.sin_family=hp->h_addrtype;
Memo1->Lines->Add("dest.sin_addr="+AnsiString(inet_ntoa(dest.sin_addr)));
}
else
{
sprintf(szTemp,"调用gethostbyname()函数失败!错误代码:%d.",WSAGetLastError());
Application->MessageBox( szTemp,"错误",MB_OK);
exit(EXIT_FAILURE);
}
}

//Create the ICMP Packet
datasize=datasize+sizeof(IcmpHeader);

icmp_data=(char *)(HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET));
recvbuff=(char *)(HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET));
if(!icmp_data)
{
Application->MessageBox( "Heapalloc() failed: "+GetLastError(),
Application->Title.c_str(),MB_OK);
}
memset(icmp_data,0,MAX_PACKET);
FillIcmpData(icmp_data,datasize);

//start sending /receiving ICMP packets
while(1)
{
static int nCount=0;
int bwrote;

if(nCount++==4)
break;
((IcmpHeader*)icmp_data)->i_cksum=0;
((IcmpHeader*)icmp_data)->timestamp=GetTickCount();
((IcmpHeader*)icmp_data)->i_seq=seq_no++;
((IcmpHeader*)icmp_data)->i_cksum=checksum((USHORT*)icmp_data,datasize);
//发送数据包
bwrote=sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));

if(bwrote==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAETIMEDOUT)
{
Memo1->Lines->Add("Ping 对方的主机时间超时!");
continue;
}
Application->MessageBox( "sendto() failed: "+WSAGetLastError(),
Application->Title.c_str(),MB_OK);
}

if(bwrote<datasize)
{
Memo1->Lines->Add("Wrote failed:"+AnsiString(bwrote));
}
bread=recvfrom(sockRaw,recvbuff,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);

if(bread==SOCKET_ERROR)
{
if(WSAGetLastError()==WSAETIMEDOUT)
{
Memo1->Lines->Add("Ping 对方的主机时间超时!");
continue;
}
Application->MessageBox( "recvfrom() failed:"+WSAGetLastError(),
Application->Title.c_str(),MB_OK);
}
DecodeICMPHeader(recvbuff,bread,&from);
Sleep(5000);
}
Memo1->Lines->Add("工作已经结束!");
if(sockRaw!=INVALID_SOCKET)
closesocket(sockRaw);
HeapFree(GetProcessHeap(),0,recvbuff);
HeapFree(GetProcessHeap(),0,icmp_data);

WSACleanup();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
tccsdn 2002-12-03
  • 打赏
  • 举报
回复
我也在写这个东西,用的是ICMP协议,不是很完善,拿去改改吧,改好了记得给我
份源代码呀,E-MAIL:tc163box@163.net
unit1.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define IP_RECORD_ROUTE 0X7
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8
#define DEF_PACKET_SIZE 32 //默认发送数据包的的大小
#define MAX_PACKET 1024 //最大发送数据包的大小
#define MAX_IP_HDR_SIZE 60 //最大IP头的大小

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

void __fastcall TForm1::FillIcmpData(char *icmp_data,int datasize)
{
IcmpHeader *icmp_hdr=NULL;
char *datapart=NULL;

icmp_hdr=(IcmpHeader*)icmp_data;
icmp_hdr->i_type=ICMP_ECHO;
icmp_hdr->i_code=0;
icmp_hdr->i_ip=(USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum=0;
icmp_hdr->i_seq=0;

datapart=icmp_data+sizeof(IcmpHeader);
memset(datapart,'E',datasize-sizeof(IcmpHeader));
}

USHORT __fastcall TForm1::checksum(USHORT *buffer,int size)
{
unsigned long cksum=0;

while(size>1)
{
cksum+=*buffer++;
size-=sizeof(USHORT);
}

if(size)
{
cksum+=*(USHORT*)buffer;
}
cksum=(cksum>>16)+(cksum & 0xffff);
cksum+=(cksum>>16);
return (USHORT)(~cksum);
}

void __fastcall TForm1::DecodeIpOptions(char *buff,int bytes)
{
IpOptionHeader *ipopt=NULL;
IN_ADDR inaddr;
int i;
HOSTENT *host=NULL;

ipopt=(IpOptionHeader*)(buff+20);
//printf("RR: ");
for(i=0;i<(ipopt->ptr/4)-1;i++)
{
inaddr.S_un.S_addr=ipopt->addr[i];
if(i!=0)
//printf(" ");
host=gethostbyaddr((char *)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET);
if(host)
Memo1->Lines->Add(AnsiString(inet_ntoa(inaddr))+AnsiString(host->h_name));
else
Memo1->Lines->Add(AnsiString(inet_ntoa(inaddr)));
}
return;
}

void __fastcall TForm1::DecodeICMPHeader(char *buff,int bytes,struct sockaddr_in *from)
{
IpHeader *iphdr=NULL;
IcmpHeader *icmphdr=NULL;
unsigned short iphdrlen;
DWORD tick;
static int icmpcount=0;

iphdr=(IpHeader*)buff;
//number of 32-bit words*4=bytes;
iphdrlen=iphdr->h_len*4;
tick=GetTickCount();

if((iphdrlen==MAX_IP_HDR_SIZE) && (!icmpcount))
DecodeIpOptions(buff,bytes);

if(bytes < iphdrlen+ICMP_MIN)
{
Application->MessageBox( "发送的数据包过小,请重新输入!",
Application->Title.c_str(),MB_OK);
}
icmphdr=(IcmpHeader*)(buff+iphdrlen);

if(icmphdr->i_type!=ICMP_ECHOREPLY)
{
Application->MessageBox("无法识别的ICMP类型!",Application->Title.c_str(),MB_OK);
}

if(icmphdr->i_ip!=(USHORT)GetCurrentProcessId())
{
Application->MessageBox("someone else's packet!",Application->Title.c_str(),MB_OK);
}

Memo1->Lines->Add(AnsiString(bytes)+"bytes from"+AnsiString(inet_ntoa(from->sin_addr)));
Memo1->Lines->Add("ICMP_SEQ="+AnsiString(inet_ntoa(from->sin_addr)));
Memo1->Lines->Add("Time:"+AnsiString(tick-icmphdr->timestamp));
icmpcount++;
return;
}

//初始化IP地址,数据包的大小,是否路由
void __fastcall TForm1::ValidataArgs()
{
int i;
bRecordRoute= FALSE; //是否选择路由选项
IpDest= NULL; //目标主机的IP地址
datasize= DEF_PACKET_SIZE; //要发送数据包的大小,大小为32字节
if(CheckBox1->Checked)
bRecordRoute=true;
else
bRecordRoute=false;
IpDest=(char *)(Edit1->Text.c_str());
}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
Edit2->Text="";
Edit1->Text="192.168.168.166";
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------

rxiao99 2002-11-21
  • 打赏
  • 举报
回复
ICMP.DLL怎么用???
我不懂电脑 2002-11-20
  • 打赏
  • 举报
回复
bcb 6中有TIdICMP组件不需要自己编程了。
szbug 2002-11-20
  • 打赏
  • 举报
回复
利用ICMP.DLL可以实现Ping的功能。。。
poweruser 2002-11-20
  • 打赏
  • 举报
回复
呵呵,同时发了一个帖子:)
poweruser 2002-11-20
  • 打赏
  • 举报
回复
使用:
CPingReply reply;
CPing PingHost;
bool bRtn = false; // 函数返回值初始为FALSE
// 先PING主机,检测网络是否畅通
bool bRet = PingHost.Ping(对方地址,reply,64,4000,32);
根据返回值判断网络是否连通
if (bRet)
{
// 可以ping到对方
}
else
{
// ping不到对方
}


希望对你有所帮助:)
flingdragon 2002-11-20
  • 打赏
  • 举报
回复
谢谢,不胜感激
poweruser 2002-11-20
  • 打赏
  • 举报
回复
cpp文件

#include <winsock.h>
#include <stdio.h>
#include "ping.h"
#pragma hdrstop

//---------------------------------------------------------------------------
#pragma package(smart_init)

#define MIN_ICMP_PACKET_SIZE 8 //minimum 8 byte icmp packet (just header)
#define MAX_ICMP_PACKET_SIZE 1024 //Maximum icmp packet size

// IP header
typedef struct tagIP_HEADER
{
unsigned int h_len:4; // length of the header
unsigned int 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;
} IP_HEADER;
typedef IP_HEADER FAR* LPIP_HEADER;

// ICMP header
typedef struct tagICMP_HEADER
{
BYTE i_type;
BYTE i_code; /* type sub code */
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
/* This is not the std header, but we reserve space for time */
ULONG timestamp;
} ICMP_HEADER;
typedef ICMP_HEADER FAR* LPICMP_HEADER;

void FillIcmpData(LPICMP_HEADER pIcmp, int nData);
BOOL DecodeResponse(char* pBuf, int nBytes, sockaddr_in* from);
USHORT GenerateIPChecksum(USHORT* pBuffer, int nSize);


///////////////////////////////// Macros & Statics ///////////////////////////

#ifdef _DEBUG
//#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BOOL CPing::sm_bAttemptedIcmpInitialise = FALSE;
lpIcmpCreateFile CPing::sm_pIcmpCreateFile = NULL;
lpIcmpSendEcho CPing::sm_pIcmpSendEcho = NULL;
lpIcmpCloseHandle CPing::sm_pIcmpCloseHandle = NULL;

__int64 CPing::sm_TimerFrequency = 0;


//Internal class which is used to ensure that the ICMP
//handle and winsock stack is closed upon exit
class _CPING
{
public:
_CPING();
~_CPING();
protected:
HINSTANCE sm_hIcmp;

friend class CPing;
};

_CPING::_CPING()
{
sm_hIcmp = NULL;
}

_CPING::~_CPING()
{
if (sm_hIcmp) {
FreeLibrary(sm_hIcmp);
sm_hIcmp = NULL;
}
WSACleanup();
}

static _CPING _cpingData;




///////////////////////////////// Implementation //////////////////////////////


BOOL CPing::Initialise() const
{
if (!sm_bAttemptedIcmpInitialise) {
sm_bAttemptedIcmpInitialise = TRUE;

//Initialise the winsock stack
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0) {
::MessageBox(NULL,"WinSock版本不匹配","ERROR",MB_OK);
return FALSE;
}

//Load up the ICMP library
_cpingData.sm_hIcmp = LoadLibrary("ICMP.DLL");
if (_cpingData.sm_hIcmp == NULL) {
::MessageBox(NULL,"无法载入'ICMP.DLL'","ERROR",MB_OK);
return FALSE;
}

//Retrieve pointers to the functions in the ICMP dll
sm_pIcmpCreateFile = (lpIcmpCreateFile) GetProcAddress(_cpingData.sm_hIcmp,"IcmpCreateFile");
sm_pIcmpSendEcho = (lpIcmpSendEcho) GetProcAddress(_cpingData.sm_hIcmp,"IcmpSendEcho" );
sm_pIcmpCloseHandle = (lpIcmpCloseHandle) GetProcAddress(_cpingData.sm_hIcmp,"IcmpCloseHandle");
if (sm_pIcmpCreateFile == NULL || sm_pIcmpSendEcho == NULL ||
sm_pIcmpCloseHandle == NULL)
::MessageBox(NULL,"'ICMP.DLL'中函数无效","ERROR",MB_OK);
}

return (sm_pIcmpCreateFile != NULL && sm_pIcmpSendEcho != NULL &&
sm_pIcmpCloseHandle != NULL);
}


BOOL CPing::IsSocketReadible(SOCKET socket, DWORD dwTimeout, BOOL& bReadible)
{
timeval timeout = {dwTimeout/1000, dwTimeout % 1000};
fd_set fds;
FD_ZERO(&fds);
FD_SET(socket, &fds);
int nStatus = select(0, &fds, NULL, NULL, &timeout);
if (nStatus == SOCKET_ERROR) {
return FALSE;
}
else {
bReadible = !(nStatus == 0);
return TRUE;
}
}

BOOL CPing::Ping(LPCTSTR pszHostName, CPingReply& pr, UCHAR nTTL, DWORD dwTimeout, UCHAR nPacketSize) const
{
//Make sure everything is initialised
if (!Initialise())
return FALSE;

LPSTR lpszAscii = (LPTSTR) pszHostName;
//Convert from dotted notation if required
unsigned long addr = inet_addr(lpszAscii);
if (addr == INADDR_NONE) {
//Not a dotted address, then do a lookup of the name
hostent* hp = gethostbyname(lpszAscii);
if (hp)
memcpy(&addr, hp->h_addr, hp->h_length);
else {
char msg[64];
sprintf(msg,"无法解析主机名:%s",pszHostName);
::MessageBox(NULL,msg,"ERROR",MB_OK);
return FALSE;
}
}

//Create the ICMP handle
HANDLE hIP = sm_pIcmpCreateFile();
if (hIP == INVALID_HANDLE_VALUE) {
::MessageBox(NULL,"无效的'ICMP'句柄","ERROR",MB_OK);
return FALSE;
}

//Set up the option info structure
IP_OPTION_INFORMATION OptionInfo;
ZeroMemory(&OptionInfo, sizeof(IP_OPTION_INFORMATION));
OptionInfo.Ttl = nTTL;

//Set up the data which will be sent
unsigned char* pBuf = new unsigned char[nPacketSize];
memset(pBuf, 'E', nPacketSize);

//Do the actual Ping
int nReplySize = sizeof(ICMP_ECHO_REPLY) + max(MIN_ICMP_PACKET_SIZE, nPacketSize);
unsigned char* pReply = new unsigned char[nReplySize];
ICMP_ECHO_REPLY* pEchoReply = (ICMP_ECHO_REPLY*) pReply;
DWORD nRecvPackets = sm_pIcmpSendEcho(hIP, addr, pBuf, nPacketSize, &OptionInfo, pReply, nReplySize, dwTimeout);

//Check we got the packet back
BOOL bSuccess = (nRecvPackets == 1);

//Check the IP status is OK (O is IP Success)
if (bSuccess && (pEchoReply->Status != 0)) {
bSuccess = FALSE;
SetLastError(pEchoReply->Status);
}

//Check we got the same amount of data back as we sent
if (bSuccess) {
bSuccess = (pEchoReply->DataSize == nPacketSize);
if (!bSuccess)
SetLastError(ERROR_UNEXP_NET_ERR);
}

//Check the data we got back is what was sent
if (bSuccess) {
char* pReplyData = (char*) pEchoReply->Data;
for (int i=0; i<nPacketSize && bSuccess; i++)
bSuccess = (pReplyData[i] == 'E');

if (!bSuccess)
SetLastError(ERROR_UNEXP_NET_ERR);
}

//Close the ICMP handle
sm_pIcmpCloseHandle(hIP);

if (bSuccess) {
//Ping was successful, copy over the pertinent info
//into the return structure
pr.Address.S_un.S_addr = pEchoReply->Address;
pr.RTT = pEchoReply->RoundTripTime;
}

//Free up the memory we allocated
delete [] pBuf;
delete [] pReply;

//return the status
return bSuccess;
}
poweruser 2002-11-20
  • 打赏
  • 举报
回复
给你一个类,可以实现ping

头文件
//These defines & structure definitions are taken from the "ipexport.h" and
//"icmpapi.h" header files as provided with the Platform SDK and
//are used internally by the CPing class. Including them here allows
//you to compile the CPing code without the need to have the full
//Platform SDK installed.

#ifndef __PING_H__
#define __PING_H__
#define max(a, b) (((a) > (b)) ? (a) : (b))

typedef unsigned long IPAddr; // An IP address.

typedef struct tagIP_OPTION_INFORMATION
{
unsigned char Ttl; // Time To Live
unsigned char Tos; // Type Of Service
unsigned char Flags; // IP header flags
unsigned char OptionsSize; // Size in bytes of options data
unsigned char FAR *OptionsData; // Pointer to options data
} IP_OPTION_INFORMATION;

typedef struct tagICMP_ECHO_REPLY
{
IPAddr Address; // Replying address
unsigned long Status; // Reply IP_STATUS
unsigned long RoundTripTime; // RTT in milliseconds
unsigned short DataSize; // Reply data size in bytes
unsigned short Reserved; // Reserved for system use
void FAR *Data; // Pointer to the reply data
IP_OPTION_INFORMATION Options; // Reply options
} ICMP_ECHO_REPLY;

typedef IP_OPTION_INFORMATION FAR* LPIP_OPTION_INFORMATION;
typedef ICMP_ECHO_REPLY FAR* LPICMP_ECHO_REPLY;
typedef HANDLE (WINAPI IcmpCreateFile)(VOID);
typedef IcmpCreateFile* lpIcmpCreateFile;
typedef BOOL (WINAPI IcmpCloseHandle)(HANDLE IcmpHandle);
typedef IcmpCloseHandle* lpIcmpCloseHandle;
typedef DWORD (WINAPI IcmpSendEcho)(HANDLE IcmpHandle, IPAddr DestinationAddress,
LPVOID RequestData, WORD RequestSize,
LPIP_OPTION_INFORMATION RequestOptions,
LPVOID ReplyBuffer, DWORD ReplySize, DWORD Timeout);
typedef IcmpSendEcho* lpIcmpSendEcho;

/////////////////////////// Classes /////////////////////////////////


struct CPingReply
{
in_addr Address; //The IP address of the replier
unsigned long RTT; //Round Trip time in Milliseconds
};

class CPing
{
public:
//Methods
BOOL Ping(LPCTSTR pszHostName, CPingReply& pr, UCHAR nTTL = 10, DWORD dwTimeout = 5000, UCHAR nPacketSize = 32) const;

protected:
BOOL Initialise() const;
static BOOL sm_bAttemptedIcmpInitialise;
static lpIcmpCreateFile sm_pIcmpCreateFile;
static lpIcmpSendEcho sm_pIcmpSendEcho;
static lpIcmpCloseHandle sm_pIcmpCloseHandle;
static BOOL IsSocketReadible(SOCKET socket, DWORD dwTimeout, BOOL& bReadible);
static __int64 sm_TimerFrequency;
};



#endif //__PING_H__
加载更多回复(2)

1,317

社区成员

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

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