//ping.h
#ifndef _CPING_H_
#define _CPING_H_
#include <Winsock2.h>
#include <Windows.h>
#pragma pack(1) #define ICMP_ECHOREPLY 0
#define ICMP_ECHOREQ 8
#define REQ_DATASIZE 32 // Echo 请求数据的大小 class CPing
{
public:
//ping host, nRetries-ping次数
bool Ping(LPCSTR pstrHost, UINT nRetries = 4); void Result(int* nElapseTime, float* fMissPack = NULL, u_char* cTTL = NULL);
//void Result(CPing::REQ_RESULT& result); private:
int WaitForEchoReply(SOCKET s);
//ICMP回应的请求和回答函数
int SendEchoRequest(SOCKET, LPSOCKADDR_IN);
DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);
u_short in_cksum(u_short *addr, int len); private:
struct REQ_RESULT
{
int nElapseTime; //请求响应时间。
u_char cTTL; //请求TTL(生存时间)
float fMissPack; //丢包率
}; REQ_RESULT m_Result;
}; // IP Header -- RFC 791
typedef struct tagIPHDR
{
u_char VIHL; // Version and IHL
u_char TOS; // Type Of Service
short TotLen; // Total Length
short ID; // Identification
short FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR; // ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char Data; // Data
}ICMPHDR, *PICMPHDR; // ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST; // ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[256];
}ECHOREPLY, *PECHOREPLY; #pragma pack() #endif

  

//ping.cpp
#include "ping.h" #pragma comment(lib, "ws2_32.lib") bool CPing::Ping(LPCSTR pstrHost, UINT nRetries)
{
//创建一个Raw套节字
SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawSocket == INVALID_SOCKET)
{
int err = WSAGetLastError();
return false;
}
int nNetTimeout = 1000;//1秒
//发送时限
setsockopt(rawSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int)); //获得主机信息
LPHOSTENT lpHost = gethostbyname(pstrHost);
if (lpHost == NULL)
{
return false;
} //构造目标套节字地址信息
struct sockaddr_in saDest;
struct sockaddr_in saSrc;
saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
saDest.sin_family = AF_INET;
saDest.sin_port = 3077;//0; DWORD dwTimeSent;
u_char cTTL;
int nRet;
int nRecvNum = 0;
int nTotalTime = 0; //多次ping
for (UINT nLoop = 0; nLoop < nRetries; ++nLoop)
{
//发送ICMP回应请求
if ((nRet = SendEchoRequest(rawSocket, &saDest)) < 0)
{
break;
} if ((nRet = WaitForEchoReply(rawSocket)) == SOCKET_ERROR)
{
break;
}
if (nRet)
{
//获得回应
if ( (dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL)) < 0)
{
nRet = dwTimeSent;
break;
}
//计算时间
nTotalTime += GetTickCount() - dwTimeSent;
//Sleep(1000);
++nRecvNum;
}
}
closesocket(rawSocket);
if (nRecvNum > 0 && nRet >= 0)
{
m_Result.nElapseTime = nTotalTime/nRetries;
m_Result.cTTL = cTTL;
m_Result.fMissPack = (float)(nRetries - nRecvNum)/nRetries;
return true;
} return false;
} //发送ICMPECHO数据包请求
int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
static ECHOREQUEST echoReq;
static int nId = 1;
static int nSeq = 1;
int nRet; //构造回应请求
echoReq.icmpHdr.Type = ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.Seq = nSeq++; for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet; //保存发送时间
echoReq.dwTime = GetTickCount(); echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); //发送请求
nRet = sendto(s,
(LPSTR)&echoReq,
sizeof(ECHOREQUEST),
0,
(LPSOCKADDR)lpstToAddr,
sizeof(SOCKADDR_IN));
//检查返回值
if (nRet == SOCKET_ERROR)
{
} return (nRet);
} //接收ICMPECHO数据包回应
DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
ECHOREPLY echoReply;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in); //接收请求回应
nRet = recvfrom(s,
(LPSTR)&echoReply,
sizeof(ECHOREPLY),
0,
(LPSOCKADDR)lpsaFrom,
&nAddrLen); //检查返回值
if (nRet == SOCKET_ERROR)
{
return nRet;
} //返回发送的时间
*pTTL = echoReply.ipHdr.TTL; return(echoReply.echoRequest.dwTime);
} //等待回应
int CPing::WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds; readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &Timeout));
} //转换地址
u_short CPing::in_cksum(u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
register int sum = 0; while( nleft > 1 ) {
sum += *w++;
nleft -= 2;
} if( nleft == 1 ) {
u_short u = 0; *(u_char *)(&u) = *(u_char *)w ;
sum += u;
} sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
} void CPing::Result(int* nElapseTime, float* fMissPack, u_char* cTTL)
{
if (nElapseTime)
{
*nElapseTime = m_Result.nElapseTime;
}
if (fMissPack)
{
*fMissPack = m_Result.fMissPack;
}
if (cTTL)
{
*cTTL = m_Result.cTTL;
}
}

  

//main.cpp
#include <stdlib.h>
#include <iostream>
#include <string>
#include "ping.h" int main(int argn, char *argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); CPing ping;
bool bResult = false;
if (argn == 2)
{
bResult = ping.Ping(argv[1]);
}
else
{
bResult = ping.Ping("www.baidu.com");
} std::cout << "result : " << bResult << std::endl;
if (bResult)
{
int nTime;
u_char nTTL;
float fMiss;
ping.Result(&nTime, &fMiss, &nTTL); std::cout << "time : " << nTime << " TTL : " << (int)nTTL << " miss : " << fMiss*100 << "% " << std::endl;
}
return 0;
}

  

vc实现ping的更多相关文章

  1. 从C++实现Ping开始说起

    在C++中实现ping功能,并不难.但真正了解ping是需要花费一番功夫的. Ping功能是在ICMP基础上实现的.IP协议并不是一个可靠的协议,它不保证数据被送达,那么,保证数据送达的工作应该由其他 ...

  2. 单片机modebus RTU通信实现,採用C语言,可适用于单片机,VC,安卓等

    当前使用的是STM32+ucos_ii编写的,能够移植到安卓以及VC .NET等方便移植使用,採用modebus poll測试过. 仅仅须要改动响应的通信接口就可以,方便多串口使用 //modebus ...

  3. 单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等(转)

    源:单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等 //modebus_rtu.c /***************************************** ...

  4. 基于VC++的网络扫描器设计与实现

    本文正文其实是自己的毕业论文,现在搬上来有两个原因. 一是之前大学的文档都放在百度网盘上,大概去年的时候百度网盘改版搞得不太稳定,文件夹移动次数一多里边就会有一些文件丢失了,也没有很在意.但前几天看申 ...

  5. 故障排错-ping dup!

    ping DUP! ping一个vc中虚拟机的地址发现如下,出现了DUP! . 解决方式如下: 1.根据mac地址找到虚拟机网卡的端口组 然后编辑绑定和故障切换,切换负责平衡

  6. vc中nmake.exe cl.exe 的使用

    首先简单介绍一下程序是如何编译链接的.程序写好之后,我们进行编译和链接来产生可执行程序.这时候,编译器为了完成编译和链接,需要知道很多信 息.比如要编译的文件是哪一个,使用哪些编译选项进行编译,编译好 ...

  7. ping域名和ping IP时速度不同的原因

    不知道大家在ping的时候有没有遇到过这样的问题:当你ping一个域名的时候,ping结果返回得很慢,但是如果直接ping这个域名的ip,结果却快很多. 直接ping ip的时候,每两次发包之间没有明 ...

  8. win7在本地windows的hosts文件中,添加新的域名映射后,不生效(问题描述:hosts文件添加自定义域名后,ping 不通域名,但是ping ip可以)

    将原来的hosts文件删除,在C:\Windows\System32\drivers\etc目录下,新建一个新的hosts文件(记住文件不要后缀,不要命名为.txt,本人在此踩过坑,或者可以百度搜索下 ...

  9. Windows7/10实现ICMP(ping命令)

    如果觉得本文如果帮到你或者你想转载都可以,只需要标注出处即可.谢谢 利用ICMP数据包.C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间 ...

随机推荐

  1. mysql之数据库备份与恢复

    备份与恢复 系统运行中,增量备份与整体备份. 例如:每周日整体备份一次,周一到周六只备份当天. 如果周五的数据出了问题,可以用周日的整体+周一.周二.周三.周四来恢复. 备份的工具: 有第三方的收费备 ...

  2. 3DES一些说明

    3DES:是在DES的基础上采用三重DES,即用两个56位的密钥K1,K2,发送方用K1加密,K2解密,再使用K1加密.接收方使用K1解密,K2加密,再使用K1解密, 3DES实现: 主要有CBC,E ...

  3. 今天写一些 有关iOS 多图片组合 成一张图片的问题。保持原像素不变

    1.要求:服务器给一张图片模板,要在模版上镂空,然后添加一些别的图片,然后组合成一张图,这个模版的像素 不是固定的,有可能比 当前手机屏幕大.所以,在组合截图的时候,有一定的要求. 贴代码: /** ...

  4. Activity的生命周期,BACK键和HOME键生命周期

    Activity的生命周期模型在Google提供的官方文档上有比较详细的一个图示 public class HelloActivity extends Activity { public static ...

  5. 删除浏览器浏览器删除cookie方法

    上班之余抽点时光出来写写博文,希望对新接触的朋友有帮助.今天在这里和大家一起学习一下删除浏览器 文章目录导航 适用范围及演示工具 什么是cookie? cookie有什么作用? ie6/ie7/ie8 ...

  6. 一个方便的shell命令,查看软件安装目录

    查看软件安装路径:whereis phpfind / -name nginx.configfind 查找 / 从根目录 -name 文件查找

  7. Android adt v22.6.2-1085508 自己主动创建 appcompat_v7 解决方法,最低版本号2.2也不会出现

    Android 开发工具升级到22.6.2在创建project时仅仅要选择的最低版本号低于4.0,就会自己主动生成一个项目appcompat_v7,没创建一个新的项目都会自己主动创建,非常是烦恼... ...

  8. 基于注解的Spring MVC整合Hibernate(所需jar包,spring和Hibernate整合配置,springMVC配置,重定向,批量删除)

    1.导入jar watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG90b3R1enVvcXVhbg==/font/5a6L5L2T/fontsize/400 ...

  9. mac中vmware tools进行磁盘压缩和vmware-tools-cli的使用方法

    前言: 高高兴兴的在vmware9.0中安装了mac10.8系统,然后学习iphone开发,但是发现下载的pdf都是基于xcode3.2.5的,又在10.8上面安装3.2.5,出现“五国”无法解决,最 ...

  10. js数组定义和获取其长度

    1.只有值组成的数组,必须先定义数组对象. 定义 var arrs=new array()或 var arrs=[]; 赋值: arrs[]="he";arrs[]="c ...