#include
#include
#include
struct ICMPheader
{
unsigned char byType;
unsigned char byCode;
unsigned short nChecksum;
unsigned short nId;
unsigned short nSequence;
};
struct IPheader
{
unsigned char byVerLen;
unsigned char byTos;
unsigned short nTotalLength;
unsigned short nId;
unsigned short nOffset;
unsigned char byTtl;
unsigned char byProtocol;
unsigned short nChecksum;
unsigned int nSrcAddr;
unsigned int nDestAddr;
};
using namespace std;
unsigned short CalcChecksum (char *pBuffer, int nLen);
bool ValidateChecksum (char *pBuffer, int nLen);
bool Initialize ();
bool UnInitialize ();
bool ResolveIP (char *pszRemoteHost, char **pszIPAddress);
void PrintUsage ();
int main(int argc, char* argv[])
{
if (argc < 2 || argc > 5)
{
PrintUsage ();
return 0;
}
if (Initialize () == false)
{
return -1;
}
int nSequence = 0;
int nMessageSize = 32; // ICMP包大小
int nTimeOut = 5000; // 请求超时值 (毫秒)
int nCount = 4; // 请求发送次数
char *pszRemoteIP = NULL, *pSendBuffer = NULL, *pszRemoteHost = NULL;
pszRemoteHost = argv [1];
for (int i = 2; i < argc; ++i)
{
switch (i)
{
case 2:
nCount = atoi (argv [2]);
break;
case 3:
nMessageSize = atoi (argv [3]);
break;
case 4:
nTimeOut = atoi (argv [4]);
break;
}
}
if (ResolveIP (pszRemoteHost, &pszRemoteIP) == false)
{
cout << "Ping request could not find host " << pszRemoteHost << ".";
cout << "Please check the name and try again." << endl;
return -1;
}
cout << "Pinging " << pszRemoteHost << " [" << pszRemoteIP << "] with " << nMessageSize << " bytes of data." << endl << endl;
ICMPheader sendHdr;
SOCKET sock;
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); // 创建原始套接字
SOCKADDR_IN dest; // 目标地址
dest.sin_addr.S_un.S_addr = inet_addr (pszRemoteIP);
dest.sin_family = AF_INET;
dest.sin_port = rand (); // 随机端口
int nResult = 0;
fd_set fdRead;
SYSTEMTIME timeSend, timeRecv;
int nTotalRoundTripTime = 0, nMaxRoundTripTime = 0, nMinRoundTripTime = -1, nRoundTripTime = 0;
int nPacketsSent = 0, nPacketsReceived = 0;
timeval timeInterval = {0, 0};
timeInterval.tv_usec = nTimeOut * 1000;
sendHdr.nId = htons (rand()); // 设置事务ID
while (nPacketsSent < nCount)
{
// 创建消息缓冲区
pSendBuffer = new char[sizeof (ICMPheader) + nMessageSize];
sendHdr.byCode = 0; // ICMP反射和应答
sendHdr.nSequence = htons (nSequence++);
sendHdr.byType = 8; // ICMP反射
sendHdr.nChecksum = 0; // Checksum
memcpy_s(pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader)); // 拷贝消息头
memset(pSendBuffer + sizeof (ICMPheader), 'x', nMessageSize);
// 计算checksum包括ICMP头和消息
sendHdr.nChecksum = htons(CalcChecksum (pSendBuffer, sizeof (ICMPheader) + nMessageSize));
memcpy_s(pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader));
nResult = sendto(sock, pSendBuffer, sizeof (ICMPheader) + nMessageSize, 0, (SOCKADDR *)&dest, sizeof (SOCKADDR_IN));
// 保存发送时间
::GetSystemTime(&timeSend);
++nPacketsSent;
if (nResult == SOCKET_ERROR)
{
cerr << endl << "An error occured in sendto operation: " << "WSAGetLastError () = " << WSAGetLastError () << endl;
UnInitialize ();
delete []pSendBuffer;
return -1;
}
FD_ZERO(&fdRead);
FD_SET(sock, &fdRead);
if ((nResult = select (0, &fdRead, NULL, NULL, &timeInterval))
== SOCKET_ERROR)
{
cerr << endl << "An error occured in select operation: " << "WSAGetLastError () = " <<
WSAGetLastError () << endl;
delete []pSendBuffer;
return -1;
}
if (nResult > 0 && FD_ISSET(sock, &fdRead))
{
// 分配空间给接收缓冲区
char *pRecvBuffer = new char[1500];
if ((nResult = recvfrom (sock, pRecvBuffer, 1500, 0, 0, 0))
== SOCKET_ERROR)
{
cerr << endl << "An error occured in recvfrom operation: " << "WSAGetLastError () = " <<
WSAGetLastError () << endl;
UnInitialize ();
delete []pSendBuffer;
delete []pRecvBuffer;
return -1;
}
// 得到接收时间
::GetSystemTime(&timeRecv);
ICMPheader recvHdr;
char *pICMPbuffer = NULL;
// 接收包含IP头
pICMPbuffer = pRecvBuffer + sizeof(IPheader);
int nICMPMsgLen = nResult - sizeof(IPheader);
// 得到ICMP头
memcpy_s(&recvHdr, sizeof(recvHdr), pICMPbuffer, sizeof(recvHdr));
// 得到IP头
IPheader ipHdr;
memcpy_s(&ipHdr, sizeof(ipHdr), pRecvBuffer, sizeof(ipHdr));
recvHdr.nId = recvHdr.nId;
recvHdr.nSequence = recvHdr.nSequence;
recvHdr.nChecksum = ntohs (recvHdr.nChecksum);
// 检查事务ID和checksum
if (recvHdr.byType == 0 &&
recvHdr.nId == sendHdr.nId &&
recvHdr.nSequence == sendHdr.nSequence &&
ValidateChecksum (pICMPbuffer, nICMPMsgLen) &&
memcmp (pSendBuffer + sizeof(ICMPheader), pRecvBuffer + sizeof (ICMPheader) + sizeof(IPheader),
nResult - sizeof (ICMPheader) - sizeof(IPheader)) == 0)
{
int nSec = timeRecv.wSecond - timeSend.wSecond;
if (nSec < 0)
{
nSec = nSec + 60;
}
int nMilliSec = abs (timeRecv.wMilliseconds - timeSend.wMilliseconds);
int nRoundTripTime = 0;
nRoundTripTime = abs (nSec * 1000 - nMilliSec);
cout << "Reply from " << pszRemoteIP << ": bytes = " << nResult - sizeof (ICMPheader) - sizeof (IPheader)
<< ", time = " << nRoundTripTime << "ms, TTL = " << (int)ipHdr.byTtl << endl;
nTotalRoundTripTime = nTotalRoundTripTime + nRoundTripTime;
if (nMinRoundTripTime == -1)
{
nMinRoundTripTime = nRoundTripTime;
nMaxRoundTripTime = nRoundTripTime;
}
else if (nRoundTripTime < nMinRoundTripTime)
{
nMinRoundTripTime = nRoundTripTime;
}
else if (nRoundTripTime > nMaxRoundTripTime)
{
nMaxRoundTripTime = nRoundTripTime;
}
++nPacketsReceived;
}
else
{
cout << "The echo reply is not correct!" << endl;
}
delete [] pRecvBuffer;
}
else
{
cout << "Request timed out." << endl;
}
delete []pSendBuffer;
}
cout << endl << "Ping statistics for " << pszRemoteIP << ":" << endl << '\t' << "Packets: Sent = " << nPacketsSent << ", Received = " <<
nPacketsReceived << ", Lost = " << (nPacketsSent - nPacketsReceived) << " (" <<
((nPacketsSent - nPacketsReceived)/(float)nPacketsSent) * 100 << "% loss)" << endl << '\t';
if (nPacketsReceived > 0)
{
cout << "\rApproximate round trip times in milli-seconds:" << endl << '\t' << "Minimum = " << nMinRoundTripTime <<
"ms, Maximum = " << nMaxRoundTripTime << "ms, Average = " << nTotalRoundTripTime / (float)nPacketsReceived << "ms" << endl;
}
cout << '\r' << endl;
if (UnInitialize() == false)
{
return -1;
}
return 0;
}
unsigned short CalcChecksum (char *pBuffer, int nLen)
{
unsigned short nWord;
unsigned int nSum = 0;
int i;
for (i = 0; i < nLen; i = i + 2)
{
nWord =((pBuffer [i] << 8)& 0xFF00) + (pBuffer [i + 1] & 0xFF);
nSum = nSum + (unsigned int)nWord;
}
while (nSum >> 16)
{
nSum = (nSum & 0xFFFF) + (nSum >> 16);
}
nSum = ~nSum;
return ((unsigned short) nSum);
}
bool ValidateChecksum (char *pBuffer, int nLen)
{
unsigned short nWord;
unsigned int nSum = 0;
int i;
for (i = 0; i < nLen; i = i + 2)
{
nWord =((pBuffer [i] << 8)& 0xFF00) + (pBuffer [i + 1] & 0xFF);
nSum = nSum + (unsigned int)nWord;
}
while (nSum >> 16)
{
nSum = (nSum & 0xFFFF) + (nSum >> 16);
}
return ((unsigned short)nSum == 0xFFFF);
}
bool Initialize ()
{
WSADATA wsaData;
if (WSAStartup (MAKEWORD (2, 2), &wsaData) == SOCKET_ERROR)
{
cerr << endl << "An error occured in WSAStartup operation: " << "WSAGetLastError () = " << WSAGetLastError () << endl;
return false;
}
SYSTEMTIME time;
::GetSystemTime(&time);
srand(time.wMilliseconds);
return true;
}
bool UnInitialize ()
{
if (WSACleanup () == SOCKET_ERROR)
{
cerr << endl << "An error occured in WSACleanup operation: WSAGetLastError () = " << WSAGetLastError () << endl;
return false;
}
return true;
}
bool ResolveIP (char *pszRemoteHost, char **pszIPAddress)
{
hostent *pHostent = gethostbyname (pszRemoteHost);
if (pHostent == NULL)
{
cerr << endl << "An error occured in gethostbyname operation: WSAGetLastError () = " << WSAGetLastError () << endl;
return false;
}
in_addr in;
memcpy_s(∈, sizeof (in_addr), pHostent->h_addr_list [0], sizeof (in_addr));
*pszIPAddress = inet_ntoa(in);
return true;
}
void PrintUsage ()
{
cout << "Usage: ping r n b t" << endl << endl;
cout << " r - Remote host" << endl;
cout << " n - Number of echo requests to send" << endl;
cout << " b - Bytes to send" << endl;
cout << " t - Timeout after these many milliseconds" << endl << endl;
cout << "\rping microsoft.com 4 32 4000" << endl << endl;
}
没有评论:
发表评论