windows中多ping网络ICMP

之前没搞过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));
	}
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随风逐流wrx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值