?? ping.cpp
字號:
///////////////////////////////////////////
// ping.cpp文件
#include "../common/initsock.h"
#include "../common/protoinfo.h"
#include "../common/comm.h"
#include <stdio.h>
CInitSock theSock;
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;
int main(int argc,char *argv[])
{
// 目的IP地址,即要Ping的IP地址
//char szDestIp[] = "192.168.0.1"; // 127.0.0.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(argv[1]);//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(" 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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -