C++实现ping程序实例
本文实例讲述了C++实现ping程序的方法。分享给大家供大家参考。具体实现方法如下:
该实例涉及ICMP数据包的发送与回显,PING程序代码如下:
DWORDWINAPIThreadProc(LPVOIDlParam) { CInitSockinitSock; HWNDhWnd=(HWND)lParam;//从参数得到句柄 charszIp[64]={0}; ::GetDlgItemTextA(hWnd,IDC_IP,szIp,sizeof(szIp));//从控件得到ip地址 //1.创建协议类型为IPPROTO_ICMP的原始套接字,设置套接字属性 SOCKETsRaw=::socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); SetTimeOut(sRaw,1000,TRUE);
//2.创建并初始化ICMP封包 charbuff[sizeof(ICMP_HDR)+32]={0}; ICMP_HDR*pIcmp=(ICMP_HDR*)buff; pIcmp->icmp_type=8; pIcmp->icmp_code=0; pIcmp->icmp_checksum=0; pIcmp->icmp_id=(USHORT)::GetCurrentProcessId(); pIcmp->icmp_sequence=0; pIcmp->icmp_timestamp=0; //填充数据 memset(&buff[sizeof(ICMP_HDR)],'E',32);
//开始发送和接收封包 USHORTnSeq=0; SOCKADDR_INdest; dest.sin_family=AF_INET; dest.sin_port=htons(0); dest.sin_addr.S_un.S_addr=inet_addr(szIp);//inet_addr("192.168.19.63");//inet_addr(szIp);220.181.111.147 CStringstrToShow=""; char*pszRevBuf=newchar[1024];//[1024]={0}; memset(pszRevBuf,0,1024); SOCKADDR_INfrom; intnFromLen=sizeof(from); while(TRUE) { //3.调用sendto发送ICMP请求 staticintnCount=0; if(nCount++==4) { break; } pIcmp->icmp_checksum=checksum((USHORT*)buff,sizeof(ICMP_HDR)+32); pIcmp->icmp_sequence=++nSeq; pIcmp->icmp_timestamp=::GetTickCount(); intnRet; nRet=::sendto(sRaw,buff,sizeof(ICMP_HDR)+32,0,(SOCKADDR*)&dest,sizeof(dest)); if(nRet==SOCKET_ERROR) { intnError=::WSAGetLastError(); strToShow+="sendtoerror\r\n"; return-1; } //4.调用recvfrom接受ICMP响应 nRet=::recvfrom(sRaw,pszRevBuf,1024,0,(sockaddr*)&from,&nFromLen); if(nRet==SOCKET_ERROR) { if(::WSAGetLastError()==WSAETIMEDOUT) { strToShow+="timeout\r\n"; continue; } strToShow+="recvfromerror\r\n"; return-1; } //解析接收到的ICMP包 intnTick=::GetTickCount(); if(nRet<sizeof(ICMP_HDR)+sizeof(IPHeader)) { strToShow+="lessbyterecved..\r\n"; } ICMP_HDR*pRecvIcmp=(ICMP_HDR*)(pszRevBuf+sizeof(IPHeader));//跳过IP头 if(pRecvIcmp->icmp_type!=0) { strToShow+="不是回显类型"; return-1; } if(pRecvIcmp->icmp_id!=::GetCurrentProcessId()) { strToShow+="不是本进程的回显包\r\n"; return-1; } CStringstrTemp; strTemp.Format("收到来自于[%s]IP的%04d字节\r\n",inet_ntoa(from.sin_addr),nRet); strToShow+=strTemp;
strTemp=""; strTemp.Format("序列号:%d\r\n",pRecvIcmp->icmp_sequence); strToShow+=strTemp;
strTemp=""; strTemp.Format("花费时间:%d\r\n",nTick-pRecvIcmp->icmp_timestamp); } strToShow+="**********************************"; ::SetDlgItemTextA(hWnd,IDC_DATA,strToShow); return0; }