Ping测试网络连接状况
2016-04-06 22:31
543 查看
.h文件:
.cpp文件:
#ifndef CPING_H #define CPING_H #include <windows.h> //这里需要导入库 Ws2_32.lib,在不同的IDE下可能不太一样 #pragma comment(lib, "Ws2_32.lib") #define DEF_PACKET_SIZE 32 #define ECHO_REQUEST 8 #define ECHO_REPLY 0 struct IPHeader { BYTE m_byVerHLen; //4位版本+4位首部长度 BYTE m_byTOS; //服务类型 USHORT m_usTotalLen; //总长度 USHORT m_usID; //标识 USHORT m_usFlagFragOffset; //3位标志+13位片偏移 BYTE m_byTTL; //TTL BYTE m_byProtocol; //协议 USHORT m_usHChecksum; //首部检验和 ULONG m_ulSrcIP; //源IP地址 ULONG m_ulDestIP; //目的IP地址 }; struct ICMPHeader { BYTE m_byType; //类型 BYTE m_byCode; //代码 USHORT m_usChecksum; //检验和 USHORT m_usID; //标识符 USHORT m_usSeq; //序号 ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部) }; struct PingReply { USHORT m_usSeq; DWORD m_dwRoundTripTime; DWORD m_dwBytes; DWORD m_dwTTL; }; class CPing { public: CPing(); ~CPing(); BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000); BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000); private: BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout); USHORT CalCheckSum(USHORT *pBuffer, int nSize); ULONG GetTickCountCalibrate(); private: SOCKET m_sockRaw; WSAEVENT m_event; USHORT m_usCurrentProcID; char *m_szICMPData; BOOL m_bIsInitSucc; private: static USHORT s_usPacketSeq; }; #endif
.cpp文件:
#include "stdafx.h" #include "CPing.h" USHORT CPing::s_usPacketSeq = 0; CPing::CPing() : m_szICMPData(NULL), m_bIsInitSucc(FALSE) { WSADATA WSAData; WSAStartup(MAKEWORD(1, 1), &WSAData); m_event = WSACreateEvent(); m_usCurrentProcID = (USHORT)GetCurrentProcessId(); if ((m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0)) != SOCKET_ERROR) { WSAEventSelect(m_sockRaw, m_event, FD_READ); m_bIsInitSucc = TRUE; m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader)); if (m_szICMPData == NULL) { m_bIsInitSucc = FALSE; } } } CPing::~CPing() { WSACleanup(); if (NULL != m_szICMPData) { free(m_szICMPData); m_szICMPData = NULL; } } BOOL CPing::Ping(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout) { return PingCore(dwDestIP, pPingReply, dwTimeout); } BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply, DWORD dwTimeout) { if (NULL != szDestIP) { return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout); } return FALSE; } BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout) { //判断初始化是否成功 if (!m_bIsInitSucc) { return FALSE; } //配置SOCKET sockaddr_in sockaddrDest; sockaddrDest.sin_family = AF_INET; sockaddrDest.sin_addr.s_addr = dwDestIP; int nSockaddrDestSize = sizeof(sockaddrDest); //构建ICMP包 int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader); ULONG ulSendTimestamp = GetTickCountCalibrate(); USHORT usSeq = ++s_usPacketSeq; memset(m_szICMPData, 0, nICMPDataSize); ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData; pICMPHeader->m_byType = ECHO_REQUEST; pICMPHeader->m_byCode = 0; pICMPHeader->m_usID = m_usCurrentProcID; pICMPHeader->m_usSeq = usSeq; pICMPHeader->m_ulTimeStamp = ulSendTimestamp; pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize); //发送ICMP报文 if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR) { return FALSE; } //判断是否需要接收相应报文 if (pPingReply == NULL) { return TRUE; } char recvbuf[256] = {"\0"}; while (TRUE) { //接收响应报文 if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT) { WSANETWORKEVENTS netEvent; WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent); if (netEvent.lNetworkEvents & FD_READ) { ULONG nRecvTimestamp = GetTickCountCalibrate(); int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize); if (nPacketSize != SOCKET_ERROR) { IPHeader *pIPHeader = (IPHeader*)recvbuf; USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4); ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen); if (pICMPHeader->m_usID == m_usCurrentProcID //是当前进程发出的报文 && pICMPHeader->m_byType == ECHO_REPLY //是ICMP响应报文 && pICMPHeader->m_usSeq == usSeq //是本次请求报文的响应报文 ) { pPingReply->m_usSeq = usSeq; pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp; pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader); pPingReply->m_dwTTL = pIPHeader->m_byTTL; return TRUE; } } } } //超时 if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout) { return FALSE;//判断网络是否畅通 } } } USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize) { unsigned long ulCheckSum=0; while(nSize > 1) { ulCheckSum += *pBuffer++; nSize -= sizeof(USHORT); } if(nSize ) { ulCheckSum += *(UCHAR*)pBuffer; } ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff); ulCheckSum += (ulCheckSum >>16); return (USHORT)(~ulCheckSum); } ULONG CPing::GetTickCountCalibrate() { static ULONG s_ulFirstCallTick = 0; static LONGLONG s_ullFirstCallTickMS = 0; SYSTEMTIME systemtime; FILETIME filetime; GetLocalTime(&systemtime); SystemTimeToFileTime(&systemtime, &filetime); LARGE_INTEGER liCurrentTime; liCurrentTime.HighPart = filetime.dwHighDateTime; liCurrentTime.LowPart = filetime.dwLowDateTime; LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000; if (s_ulFirstCallTick == 0) { s_ulFirstCallTick = GetTickCount(); } if (s_ullFirstCallTickMS == 0) { s_ullFirstCallTickMS = llCurrentTimeMS; } return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS); }
相关文章推荐
- 一次复杂而简单的网络诊断
- 牛客网每日打卡-网络基础-20160406
- [C#基础]网络编程(三):protobuf-net
- <meta>中的http-equiv的参数值
- https://github.com/oneuijs/You-Dont-Need-jQuery
- bzoj 1061: [Noi2008]志愿者招募(线性规划+网络流)
- hdu 5437 Alisha’s Party(长春网络赛——优先队列)
- HttpClient学习
- windows8.1/10 添加网络打印机的方法
- apache之https
- nginx记录网站慢请求(ngx_http_log_request_speed)
- 网络编程(1)
- TCP三次握手的思考,为什么要有三次握手
- AVPlayer(网络音频资源)的封装
- 关于网络请求中无法访问HttpRequestBase
- HttpURLConnection与HttpClient区别及联系
- 写给后端程序员的HTTP缓存原理介绍
- HTTP状态码
- 神经网络
- TCP中的多线程