Ping的代码

这是以前自己写的Ping代码, 以ICMP协议为基础
ICMP协议参考: http://baike.baidu.com/view/30564.htm
--------------------------------------------------------------------------------------------------------------------------------------------------
 
//Please link library WS2_32.LIB at first.
// ICMP.h
#include <windows.h>
#ifndef __ICMP_H__
#define __ICMP_H__

#define ICMP_ECHO 8
#define ICMP_REPLAY 0
#define MAX_DATA_SIZE 32
#define ICMP_MIN 8

#pragma pack(1)

typedef struct tagICMPHeader
{
    UCHAR type;
    UCHAR code;
    USHORT checkSum;
    USHORT ID;
    USHORT SeqNumber;
}ICMPHeader, *PICMPHeader;

#pragma pack()
#pragma pack(1)

typedef struct tagIPHeader
{
    BYTE h_len:4;
    BYTE version:4;
    BYTE tos;
    USHORT total_len;
    USHORT ID;
    USHORT flags;
    BYTE ttl;
    BYTE proto;
    USHORT checksum;
    ULONG source_ip;
    ULONG dest_ip;
}IPHeader, *PIPHeader;

#pragma pack()

#endif  // ICMP_H
 
// Ping.h
#include "ICMP.H"
#include <iostream>
using namespace std;
#ifndef __PING_H__
#define __PING_H__

#pragma pack(1)

typedef struct tagPingPacket
{
    ICMPHeader icmp_header;
    DWORD dwTime;
}PingPacket, *PPingPacket;

#pragma pack()
class Ping
{
public:
    Ping();
    ~Ping();
    BOOL StartClient();
 
private:
    void PackPingPacket(PingPacket& ping_packet);
    int UnPackPingPacket();
    int Configuration();
    int ReceivePacket();
    int SendPacket();
    DWORD InitializeConnection();
    int UnitializeConnection();
    DecodePingPacket(const IPHeader& ip_header, const int recvPacketLen);
    friend USHORT ip_checksum(USHORT* buffer, int size);
    friend void ReadIPAddress(unsigned long IPAddress);
private:
    SOCKET sock;
    sockaddr_in dest;
    sockaddr_in source;
};
#endif  // PING_H
 
PING.cpp
#include "PING.H"
const TCHAR* DEFAULT_ADDRESS = TEXT("220.181.27.48");   // LocalHost
const int TIMEOUT = 1000;                                // 1 second
Ping::Ping()
{
    InitializeConnection();
}
Ping::~Ping()
{
    UnitializeConnection();
}
BOOL Ping::StartClient()
{
    while(true)
    {
        if (SendPacket())
        {
             return FALSE;
        }
        if (ReceivePacket())
        {
            return FALSE;
        }
        Sleep(1000);
    }
    return TRUE;
}
 
DWORD Ping::InitializeConnection()
{
    cout << "Initialize Connection!" << endl;
    WSAData wsaData;
    if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
    {
        cout << "Startup error!" << endl;
        return GetLastError();
    }
    sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    if (sock < 0)
    {
        cout << "Create socket error!" << endl;
        return GetLastError();
    }
 
    if (Configuration())
    {
        return GetLastError();
    }
 
    return 0;
}
 
int Ping::Configuration()
{
    int ttl = TIMEOUT;
 
    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&ttl, sizeof(ttl)) == SOCKET_ERROR)
    {
        cout << "Error in Configuration, error code:" <<  GetLastError() << endl;
        return GetLastError();
    }
 
    memset(&dest, 0, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = inet_addr(DEFAULT_ADDRESS);
    return 0;
}
 
int Ping::UnitializeConnection()
{
    WSACleanup();
    closesocket(sock);
    cout << "Unitialize Connection!" << endl;
    return 0;
}
 
void Ping::PackPingPacket(PingPacket& ping_packet)
{
    static USHORT ID = 1;
    static USHORT SeqNumber = 1;
    ping_packet.icmp_header.type = ICMP_ECHO;
    ping_packet.icmp_header.code = 0;
    ping_packet.icmp_header.checkSum = 0;
    ping_packet.icmp_header.ID = ID++;
    ping_packet.icmp_header.SeqNumber = SeqNumber++;
    ping_packet.dwTime = GetTickCount();
    ping_packet.icmp_header.checkSum = ip_checksum((USHORT*)&ping_packet, sizeof(ping_packet));
}
 
int Ping::UnPackPingPacket()
{
    return 0;
}
 
int Ping::SendPacket()
{
    PingPacket ping_packet;
    PackPingPacket(ping_packet);
    int retValue = sendto(sock,                                  // Socket
                                 (const char*)&ping_packet,    // Buffer
                                 sizeof(ping_packet),
                                 0,                                       // Flag
                                 (const sockaddr*)&dest,        // The Pointer to Socket Address 
                                 sizeof(dest));                       // Size of Socket Address
    if (retValue < 0)
    {
        cout << "Error in send Packet, error code" << GetLastError() << endl;
        return GetLastError();
    }
    return 0;
}
 
int Ping::ReceivePacket()
{
    // effetive will be worse?
    IPHeader* recv_buf = (IPHeader*)new TCHAR[MAX_DATA_SIZE];
    if (recv_buf == NULL)
    {
        return GetLastError();
    }
    int fromlen = sizeof(source);
    int retValue = recvfrom(sock,
                                    (char*)recv_buf,
                                    MAX_DATA_SIZE, 
                                    0,
                                    (sockaddr*)&source,
                                    &fromlen);
    if (retValue < 0)
    {
        cout << "Error in receive packet, error code" << GetLastError() << endl;
        return GetLastError();
    }
    else
    {
        // Decode ping packet
        DecodePingPacket(*recv_buf, retValue);
    }
    delete []recv_buf;
    recv_buf = NULL;
    return 0;
}
 
USHORT ip_checksum(USHORT* buffer, int size)
{
    unsigned long cksum = 0;
   
    // Sum all the words together, adding the final byte if size is odd
    while (size > 1) {
        cksum += *buffer++;
        size -= sizeof(USHORT);
    }
    if (size) {
        cksum += *(UCHAR*)buffer;
    }
 
    // Do a little shuffling
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
   
    // Return the bitwise complement of the resulting mishmash
    return (USHORT)(~cksum);
}
 
void ReadIPAddress(unsigned long IPAddress)
{
    printf("%d.%d.%d.%d/n", UCHAR(IPAddress),
                                       UCHAR(IPAddress >> 8),
                                       UCHAR(IPAddress >> 16),
                                       UCHAR(IPAddress >> 24));
}
 
int Ping::DecodePingPacket(const IPHeader& ip_header, const int recvPacketLen)
{
    cout << "IPHeader->source_ip:";
    ReadIPAddress(ip_header.source_ip);
    printf("IPHeader->total_len: %d/r/n", ip_header.total_len);
    printf("IPHeader->tos: %d/r/n", ip_header.tos);
    printf("IPHeader->ID:%d/r/n", ip_header.ID);
    printf("IPheader->ttl:%d/r/n", ip_header.ttl);
    USHORT ipheader_len = ip_header.h_len * 4;
 
    if (recvPacketLen < ipheader_len + ICMP_MIN)
    {
        // Packet is too small
        cout << "Receive packet is too small" << endl;
        return -1;
    }
   
    PingPacket *pingpacket = (PingPacket*)((char*)&ip_header + ipheader_len);
    if (pingpacket == NULL)
    {
        cout << "ICMP Header is NULL" << endl;
        return -1;
    }
 
    if (pingpacket->icmp_header.type == ICMP_REPLAY)
    {
        cout << "Reply Packet" << endl;
        cout << "time:" << int (GetTickCount() - pingpacket->dwTime) << endl;
    }
   
    return 0;
}
 
main.cpp
#include "PING.H"
int main()
{
    Ping myping;
    if (myping.StartClient())
    {
        cout << "Ping Machine Successfully!" << endl;
    }
    else
    {
         cout << "Ping Machine Error!" << endl;
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值