思路:ping网关,若能ping通则与内网连接,否则认为没有与内网连接。 实现如下: bool ping() { // 目的IP地址,即要Ping的IP地址 //char szDestIp[] = "119.147.15.13"; // 127.0.0.1 const char * szDestIp = getGateway(); //if(szDestIp == NULL) if(strlen(szDestIp) == 0) return false; // 创建原始套节字 SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); // 设置接收超时 SetTimeout(sRaw, 1000, TRUE); // 设置目的地址 SOCKADDR_IN dest; dest.sin_family = AF_INET; dest.sin_port = htons(0); dest.sin_addr.S_un.S_addr = inet_addr(szDestIp); // 创建ICMP封包 char buff[sizeof(ICMP_HDR) + 32]; ICMP_HDR* pIcmp = (ICMP_HDR*)buff; // 填写ICMP封包数据,请求一个ICMP回显 pIcmp->icmp_type = 8; pIcmp->icmp_code = 0; pIcmp->icmp_id = (USHORT)::GetCurrentProcessId(); pIcmp->icmp_checksum = 0; pIcmp->icmp_sequence = 0; // 填充数据部分,可以为任意 memset(&buff[sizeof(ICMP_HDR)], 'E', 32); // 开始发送和接收ICMP封包 USHORT nSeq = 0; char recvBuf[1024]; SOCKADDR_IN from; int nLen = sizeof(from); for(int i = 0; i<4; i++) { static int nCount = 0; int nRet; // ping次数 if(nCount++ == 1000) break; pIcmp->icmp_checksum = 0; pIcmp->icmp_timestamp = ::GetTickCount(); pIcmp->icmp_sequence = nSeq++; pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32); nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest)); if(nRet == SOCKET_ERROR) { printf(" sendto() failed: %d /n", ::WSAGetLastError()); return false; } nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen); if(nRet == SOCKET_ERROR) { if(::WSAGetLastError() == WSAETIMEDOUT) { printf(" timed out/n"); continue; } printf(" recvfrom() failed: %d/n", ::WSAGetLastError()); return false; } else return true; } return false; }