#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mbnapi.h" #include #include //for mobileDial #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "mbnapi_uuid.lib") #include "SpBase.h" #if defined(SPBASE_API) #define printf(fmt, ...) \ Dbg(fmt, __VA_ARGS__) #else #define printf(fmt, ...) \ printf(fmt "\n", __VA_ARGS__) #endif //路由选项类型,占用3字节 #define IP_RECORD_ROUTE 0x7 //IP时间戳选项 #define IP_TIMESTAMP 0x44 #define DEFAULT_PACKET_SIZE 32 #define MAX_PACKET 1024 + 12 + 20 + 1 #define MAX_IP_HDR_SIZE 60 //回送请求或回答 #define ICMP_ECHO 8 #define ICMP_ECHO_REPLY 0 #define MAX_UNSIGNED_SHORT 65535 #define DEFAULT_TIMEOUT 3000 #define DEFAULT_INTERVAL 1000 typedef struct _iphdr { //注意顺序,网络字节序,大端 unsigned int h_len:4; unsigned int version:4; unsigned char tos; // type of service unsigned short total_len; // Total length of the packet unsigned short ident; // Unique identifier unsigned short frag_and_flags; // 标志和片偏移 unsigned char ttl; // time to live unsigned char proto; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; }IpHeader; #define DEFAULT_IP_HEAD_SIZE 20 typedef struct _icmphdr { BYTE btType; //type of icmp BYTE btCode; // code of icmp 进一步定义查询或消息的类型 默认0 USHORT usCksum; //16bits 对ICMP头内容的一个补余求和 USHORT usId; //identification USHORT usSeq; //选项值 ULONG ulTimestamp; }IcmpHeader; #define DEFAULT_ICMP_HEAD_SIZE sizeof(IcmpHeader) const double MAX_GSM_SIGNAL_STRENGTH = 31.0; class CTWPing { public: CTWPing(); ~CTWPing(void); int Initial(const char* destIp, int nDataSize = 0, int nTimeout = 0, int nInterval = 0); //0 结束成功返回 //1 创建套接字失败 //2 超时达上限 //3 其他错误达到上限 int Ping(); //0 结束成功返回 //1 创建套接字失败 //2 超时 //3 其他错误 //4 无效需要重新尝试 int PingOnce(); void TerminatePing() { m_bCancelPing = TRUE; } SOCKET m_hSocket; SOCKADDR_IN m_addrDest; SOCKADDR_IN m_addrSource; void Cleanup(bool bWSACleanup = false) //Consistent with FSM -Josephus@2017823 11:09:38 { if(m_hSocket != INVALID_SOCKET) { closesocket(m_hSocket); m_hSocket = INVALID_SOCKET; } if(m_recvBuf != NULL) { HeapFree(GetProcessHeap(), 0, m_recvBuf); m_recvBuf = NULL; } if(m_icmpData != NULL) { HeapFree(GetProcessHeap(), 0, m_icmpData); m_icmpData = NULL; } while(bWSACleanup && TRUE) { if(WSACleanup() != ERROR_SUCCESS && WSAGetLastError() == WSANOTINITIALISED) break; } m_bInited = false; } bool IsValid() const { return m_bInited; } private: int m_nDataSize; int m_nTimeout; int m_nInterval; char m_szIP[128]; char* m_icmpData; char* m_recvBuf; BOOL m_bCancelPing; bool m_bInited; USHORT m_usPacketSeqNo; USHORT GetCurrentSeqNo() { return m_usPacketSeqNo; } USHORT IncreaseCurSeqNo() { if(m_usPacketSeqNo < MAX_UNSIGNED_SHORT) { m_usPacketSeqNo++; } else { m_usPacketSeqNo = 0; } return m_usPacketSeqNo; } int InitICMPData(); //-1 重置套接字并重新发送 //-2 重新接收 int DecodeICMPData(int bytes); int CreateSocket() { if(m_hSocket != INVALID_SOCKET) { closesocket(m_hSocket); m_hSocket = INVALID_SOCKET; } m_hSocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED); if(m_hSocket == INVALID_SOCKET) { printf("WSASocket() failed with status %d", WSAGetLastError()); return -1; } int bread = setsockopt(m_hSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&m_nTimeout, sizeof(m_nTimeout)); if(bread == SOCKET_ERROR) { printf("Warning: Setsockopt(SO_SNDTIMEO) failed with status %d", WSAGetLastError()); } bread = setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&m_nTimeout, sizeof(m_nTimeout)); if(bread == SOCKET_ERROR) { printf("Warning: Setsockopt(SO_RCVTIMEO) failed with status %d", WSAGetLastError()); } m_usPacketSeqNo = 0; return 0; } void CloseSocket() { if(m_hSocket != INVALID_SOCKET) { closesocket(m_hSocket); m_hSocket = INVALID_SOCKET; } } USHORT CheckSum(USHORT* buffer, int nSize) { ULONG checkSum = 0; while(nSize > 1) { checkSum += *buffer++; nSize -= sizeof(USHORT); } if(nSize) { checkSum += *(UCHAR*)buffer; } checkSum = (checkSum >> 16) + (checkSum & 0xffff); checkSum += (checkSum >> 16); return (USHORT)(~checkSum); } };