相关参考 : http://baike.baidu.com/view/493712.htm
#define __GENERAL_H__
extern USHORT ip_checksum(USHORT* buffer, int size);
void ReadIPAddress(unsigned long IPAddress);
#include "General.h"
#include <stdio.h>
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));
}
----------------------------------------------------------------------------------------------------------
ICMP.h
#include <windows.h>
#ifndef __ICMP_H__
#define __ICMP_H__
#define ICMP_ECHO 8 // Echo ICMP Packet
#define ICMP_REPLAY 0 // Replay ICMP Packet
#define MAX_DATA_SIZE 1024
#define ICMP_MIN 8
#define ICMP_TIMEOUT 11 // Time out ICMP Packet
#define DEFAULT_ICMP_SIZE 44 // The Default ICMP Packet Size
#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
-------------------------------------------------------------------------------------------------------
Tracert.h
#include "ICMP.H"
#include "General.h"
#include <iostream>
using namespace std;
#ifndef __TRACERT_H__
#define __TRACERT_H__
#define TRACERT_DATA_PART_SIZE (DEFAULT_ICMP_SIZE - sizeof(ICMPHeader))
#pragma pack(1)
typedef struct tagTracertPacket
{
ICMPHeader icmp_header;
BYTE data_part[TRACERT_DATA_PART_SIZE];
}TracertPacket, *PTracertPacket;
#pragma pack()
class Tracert
{
public:
Tracert();
~Tracert();
BOOL StartClient();
private:
void PackTracertPacket(TracertPacket& tracert_packet);
int UnPackTracertPacketPacket();
int Configuration();
int ReceivePacket();
int SendPacket();
DWORD InitializeConnection();
int UnitializeConnection();
int DecodeTracertPacket(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 // TRACERT_H
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h> //Need the support of WinSock2
#include <ws2tcpip.h> //When setting the level of IPPROTO_IP
#include "Tracert.h"
static const TCHAR* DEFAULT_ADDRESS = TEXT("220.181.18.155"); // BaiDu Address
static const int TIMEOUT = 1000; // 1 second
{
InitializeConnection();
}
{
UnitializeConnection();
}
{
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();
}
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(DEFAULT_ADDRESS);
return 0;
}
{
static int livetime = 1;
int retValue=setsockopt(sock,IPPROTO_IP,IP_TTL,(char *)&livetime,sizeof(int));
if (retValue < 0)
{
cout << "Error in Set Tracert Packet Time, error code" << GetLastError() << endl;
return GetLastError();
}
else
{
livetime++;
}
TracertPacket tracert_packet;
PackTracertPacket(tracert_packet);
retValue = sendto(sock, // Socket
(const char*)&tracert_packet, // Buffer
sizeof(tracert_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;
}
{
// 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
retValue = DecodeTracertPacket(*recv_buf, retValue);
}
delete []recv_buf;
recv_buf = NULL;
return retValue;
}
{
//static USHORT ID = 1;
static USHORT SeqNumber = 1;
tracert_packet.icmp_header.type = ICMP_ECHO;
tracert_packet.icmp_header.code = 0;
tracert_packet.icmp_header.checkSum = 0;
tracert_packet.icmp_header.ID = (USHORT)GetCurrentProcessId();
tracert_packet.icmp_header.SeqNumber = SeqNumber++;
memset(tracert_packet.data_part, 'E', TRACERT_DATA_PART_SIZE);
tracert_packet.icmp_header.checkSum = ip_checksum((USHORT*)&tracert_packet, sizeof(tracert_packet));
}
{
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;
}
TracertPacket *tracertpacket = (TracertPacket*)((char*)&ip_header + ipheader_len);
if (tracertpacket == NULL)
{
cout << "ICMP Header is NULL" << endl;
return -1;
}
if (tracertpacket->icmp_header.type == ICMP_TIMEOUT && tracertpacket->icmp_header.code == 0)
{
//cout << "Reply Packet" << endl;
//cout << "time:" << int (GetTickCount() - pingpacket->dwTime) << endl;
cout << "Route Address:";
ReadIPAddress(ip_header.source_ip);
}
if(tracertpacket->icmp_header.type==ICMP_REPLAY &&
tracertpacket->icmp_header.ID==GetCurrentProcessId())
{
//printf("%2d: %-15s %4dms/n",icmpcount++,
// inet_ntoa(from->sin_addr),tick-cStartTickCount);
cout << "Route Address:";
ReadIPAddress(ip_header.source_ip);
printf("Trace complete!/n");
return TRANSFER_OVER;
}
}
{
int flag = 0;
while(true)
{
if (SendPacket())
{
return FALSE;
}
flag = ReceivePacket();
if (flag == TRANSFER_OVER)
{
return TRUE;
}
else if (flag)
{
return FALSE;
}
Sleep(1000);
}
return TRUE;
}
{
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();
}
{
return GetLastError();
}
cout << "-Initialize Connection!" << endl;
return 0;
}
{
WSACleanup();
closesocket(sock);
cout << "Unitialize Connection!" << endl;
return 0;
}
{
return 0;
}
{
Tracert tracert_Program;
tracert_Program.StartClient();
return 0;
}