我们单位局域网有若干台服务器,通过一台CISCO3550交换机连接在一起,IP地址分别为10.230.0.10-15,是可以PING通的。我想利用VC++6.0做一个程序,在一个PC机上,如果能够PING通这台服务器,则提示某某服务器的网络连接正常,如果PING不通,则提示某某服务器的网络连接不正常。这个程序用VC++好实现吗?网上有类似的程序的源代码吗?

解决方案 »

  1.   

    The following example sends an ICMP echo request to the IP address 123.456.789.0 and prints the information received from that request.#include <winsock2.h>
    #include <iphlpapi.h>
    #include <icmpapi.h>
    #include <stdio.h>int __cdecl main(int argc, char **argv)  {    // Declare and initialize variables
        
        HANDLE hIcmpFile;
        unsigned long ipaddr = INADDR_NONE;
        DWORD dwRetVal = 0;
        char SendData[] = "Data Buffer";
        LPVOID ReplyBuffer = NULL;
        DWORD ReplySize = 0;

        // Validate the parameters
        if (argc != 2) {
            printf("usage: %s IP address\n", argv[0]);
            return 1;
        }    ipaddr = inet_addr(argv[1]);
        if (ipaddr == INADDR_NONE) {
            printf("usage: %s IP address\n", argv[0]);
            return 1;
        }
        
        hIcmpFile = IcmpCreateFile();
        if (hIcmpFile == INVALID_HANDLE_VALUE) {
            printf("\tUnable to open handle.\n");
            printf("IcmpCreatefile returned error: %ld\n", GetLastError() );
            return 1;
        }        ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
        ReplyBuffer = (VOID*) malloc(ReplySize);
        if (ReplyBuffer == NULL) {
            printf("\tUnable to allocate memory\n");
            return 1;
        }    
        
        
        dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), 
            NULL, ReplyBuffer, ReplySize, 1000);
        if (dwRetVal != 0) {
            PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
            struct in_addr ReplyAddr;
            ReplyAddr.S_un.S_addr = pEchoReply->Address;
            printf("\tSent icmp message to %s\n", argv[1]);
            if (dwRetVal > 1) {
                printf("\tReceived %ld icmp message responses\n", dwRetVal);
                printf("\tInformation from the first response:\n"); 
            }    
            else {    
                printf("\tReceived %ld icmp message response\n", dwRetVal);
                printf("\tInformation from this response:\n"); 
            }    
            printf("\t  Received from %s\n", inet_ntoa( ReplyAddr ) );
            printf("\t  Status = %ld\n", 
                pEchoReply->Status);
            printf("\t  Roundtrip time = %ld milliseconds\n", 
                pEchoReply->RoundTripTime);
        }
        else {
            printf("\tCall to IcmpSendEcho failed.\n");
            printf("\tIcmpSendEcho returned error: %ld\n", GetLastError() );
            return 1;
        }
        return 0;
    }    
        
      

  2.   

    http://tangentsoft.net/wskfaq/examples/dllping.html
     Examples: Ping: ICMP.DLL Method
      

  3.   

    给你个,供参考
    #include <stdio.h>
    #include <winsock2.h>
    #pragma comment(lib,"ws2_32.lib")typedef struct icmp_hdr
    {
        unsigned char   icmp_type; // 消息类型
        unsigned char   icmp_code; // 代码
        unsigned short  icmp_checksum; // 校验和
    // 下面是回显头
        unsigned short  icmp_id; // 用来惟一标识此请求的ID号,通常设置为进程ID
        unsigned short  icmp_sequence; // 序列号
        unsigned long   icmp_timestamp; // 时间戳
    } ICMP_HDR, *PICMP_HDR;typedef struct _IPHeader // 20字节的IP头
    {
        UCHAR     iphVerLen;      // 版本号和头长度(各占4位)
        UCHAR     ipTOS;          // 服务类型 
        USHORT    ipLength;       // 封包总长度,即整个IP报的长度
        USHORT    ipID;   // 封包标识,惟一标识发送的每一个数据报
        USHORT    ipFlags;       // 标志
        UCHAR     ipTTL;       // 生存时间,就是TTL
        UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
        USHORT    ipChecksum;     // 校验和
        ULONG     ipSource;       // 源IP地址
        ULONG     ipDestination;  // 目标IP地址
    } IPHeader, *PIPHeader; USHORT checksum(USHORT* buff, int size);BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv = TRUE);int main()
    {
    // 目的IP地址,即要Ping的IP地址
    char szDestIp[] = "127.0.0.1"; // 127.0.0.1 WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2,2);
    if(::WSAStartup(sockVersion, &wsaData) != 0)
    {
    return -1;
    } // 创建原始套节字
    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封包数据
    pIcmp->icmp_type = 8; // 请求一个ICMP回显
    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);
    while(TRUE)
    {
    static int nCount = 0;
    int nRet;
    if(nCount++ == 4)
    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 -1;
    }
    nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
    if(nRet == SOCKET_ERROR)
    {
    if(::WSAGetLastError() == WSAETIMEDOUT)
    {
    printf("Request timed out\n");
    continue;
    }
    printf(" recvfrom() failed: %d\n", ::WSAGetLastError());
    return -1;
    } // 下面开始解析接收到的ICMP封包
    int nTick = ::GetTickCount();
    if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
    {
    printf(" Too few bytes from %s \n", ::inet_ntoa(from.sin_addr));
    }
    // 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头
    ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
    if(pRecvIcmp->icmp_type != 0) // 回显
    {
    printf(" nonecho type %d recvd \n", pRecvIcmp->icmp_type);
    return -1;
    } if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())
    {
    printf(" someone else's packet! \n");
    return -1;
    }

    printf(" %d bytes from %s:", nRet, inet_ntoa(from.sin_addr));
    printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);
    printf(" time: %d ms", nTick - pRecvIcmp->icmp_timestamp);
    printf(" \n"); ::Sleep(1000);
    } return 0;
    }USHORT checksum(USHORT* buff, int size)
    {
    unsigned long cksum = 0;
    while(size>1)
    {
    cksum += *buff++;
    size -= sizeof(USHORT);
    }
    // 是奇数
    if(size)
    {
    cksum += *(UCHAR*)buff;
    }
    // 将32位的chsum高16位和低16位相加,然后取反
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
    return (USHORT)(~cksum);
    }BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv)
    {
    int ret = ::setsockopt(s, SOL_SOCKET, 
    bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
    return ret != SOCKET_ERROR;
    }