之前没搞过ICMP,第一次弄,遇到好多坑,其中在接收ICMP消息时无法指定ip这个坑困扰了好久,最后在网上找到一种解决方法;直接看效果吧!!

其中我获取ip状态直接扔到线程池里面处理的
struct DevicePingMsg
{
	DevicePingMsg()
	{
		ipStr = "";
		sendPacketNum = 0;
		receivePacketNum = 0;
		lossPacketNum = 0;
		lossPacketRate = "";
		minRespondTime = 0;
		maxRespongTime = 0;
		ttl = 0;
	}
	/// ip地址
	QString		ipStr;
	/// 发包数 
	int			sendPacketNum;
	/// 收包数
	int			receivePacketNum;
	/// 丢包数
	int			lossPacketNum;
	/// 丢包率
	QString		lossPacketRate;
	/// 最小响应时间
	int			minRespondTime;
	/// 最大响应时间
	int			maxRespongTime;
	/// TTL
	int			ttl;
};
typedef struct {
	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 *OptionsData;                // Pointer to options data
} IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
typedef struct {
	DWORD Address;                             // Replying address
	unsigned long  Status;                     // Reply status
	unsigned long  RoundTripTime;              // RTT in milliseconds
	unsigned short DataSize;                   // Echo data size
	unsigned short Reserved;                   // Reserved for system use
	void *Data;                                // Pointer to the echo data
	IP_OPTION_INFORMATION Options;             // Reply options
} IP_ECHO_REPLY, *PIP_ECHO_REPLY;void PingDevice::PingProc(QString ipStr, void *pUser)
{
	typedef HANDLE(WINAPI* pfnHV)(VOID);
	typedef BOOL(WINAPI* pfnBH)(HANDLE);
	typedef DWORD(WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
	pfnHV pIcmpCreateFile;
	pfnBH pIcmpCloseHandle;
	pfnDHDPWPipPDD pIcmpSendEcho;
	_hIcmp = LoadLibrary(TEXT("ICMP.DLL"));
	if (NULL == _hIcmp)
	{
		return;
	}
	pIcmpCreateFile = (pfnHV)GetProcAddress(_hIcmp, "IcmpCreateFile");
	pIcmpCloseHandle = (pfnBH)GetProcAddress(_hIcmp, "IcmpCloseHandle");
	pIcmpSendEcho = (pfnDHDPWPipPDD)GetProcAddress(_hIcmp, "IcmpSendEcho");
	if ((pIcmpCreateFile == 0) || (pIcmpCloseHandle == 0) || (pIcmpSendEcho == 0))
	{
		return;
	}
	HANDLE hIP = pIcmpCreateFile();
	if (hIP == INVALID_HANDLE_VALUE)
	{
		return;
	}
	char acPingBuffer[64];
	memset(acPingBuffer, '\xAA', sizeof(acPingBuffer));
	PIP_ECHO_REPLY pIpe = (PIP_ECHO_REPLY)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer));
	if (pIpe == 0)
	{
		return;
	}
	pIpe->Data = acPingBuffer;
	pIpe->DataSize = sizeof(acPingBuffer);
	DWORD	  dwElapsed = 0;
	int sendNum = 0;
	int receiveNum = 0;
	int lostNum = 0;
	int maximum = 0;
	int minimum = 0;
	m_bRuning = true;
	int	timeElapsed;
	DialogDeviceMorePing* _this = static_cast<DialogDeviceMorePing*>(pUser);
	if (!_this)
		return;
	while (m_bRuning)
	{
		struct hostent* phe;
		if ((phe = gethostbyname(ipStr.toStdString().data())) == 0)
		{
			dwElapsed = -1;
		}
		sendNum++;
		auto start = std::chrono::system_clock::now();
		DWORD dwStatus = pIcmpSendEcho(hIP, *((DWORD*)phe->h_addr_list[0]),
			acPingBuffer, sizeof(acPingBuffer), NULL, pIpe,
			sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer), 10);
		if (dwStatus != 0)
		{
			dwElapsed = pIpe->RoundTripTime;
		}
		else
		{
			if (11010 == GetLastError())
			{
				dwElapsed = -1;
			}
		}
		if (dwElapsed != -1)
		{
			receiveNum++;
			auto end = std::chrono::system_clock::now();
			auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
			DevicePingMsg pingMsg;
			pingMsg.ttl = pIpe->Options.Ttl;
			pingMsg.ipStr = ipStr;
			pingMsg.sendPacketNum = sendNum;
			pingMsg.lossPacketNum = lostNum;
			pingMsg.receivePacketNum = receiveNum;
			float lossRate = (lostNum * 1.0) / (sendNum * 1.0);
			pingMsg.lossPacketRate = QString::number(lossRate, 'f', 2);
			timeElapsed = dwElapsed;
			if (timeElapsed > maximum)
				maximum = timeElapsed;
			if (timeElapsed < minimum)
				minimum = timeElapsed;
			pingMsg.minRespondTime = minimum;
			pingMsg.maxRespongTime = maximum;
			_this->UpdatePingMsg(pingMsg, false);
		}
		else
		{
			DevicePingMsg pingMsg;
			lostNum++;
			pingMsg.ttl = pIpe->Options.Ttl;
			pingMsg.ipStr = ipStr;
			pingMsg.sendPacketNum = sendNum;
			pingMsg.lossPacketNum = lostNum;
			pingMsg.receivePacketNum = receiveNum;
			float lossRate = (lostNum * 1.0) / (sendNum * 1.0);
			pingMsg.lossPacketRate = QString::number(lossRate, 'f', 2);
			_this->UpdatePingMsg(pingMsg, true);
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
	}
}



















