#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Winsock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<MSWSOCK.H>
#pragma comment(lib,"WS2_32.lib")
#define DEF_ICMP_TIMEOUT 3000
#define ICMP_ECHO_REQUEST 8
#define DEF_ICMP_DATA_SIZE 20
#define DEF_ICMP_PACK_SIZE 32
#define MAX_ICMP_PACKET_SIZE 1024
#define ICMP_ECHO_REPLY 0
typedef struct
{
byte h_len_ver;
byte tos;
unsigned short total_len;
unsigned short ident;
unsigned short frag_and_flags;
byte ttl;
byte proto;
unsigned short cksum;
unsigned long sourceIP;
unsigned long destIP;
} IP_HEADER;
typedef struct
{
byte type;
byte code;
unsigned short cksum;
unsigned short id;
unsigned short seq;
unsigned int choose;
} ICMP_HEADER;
typedef struct
{
int usSeqNo;
DWORD dwRoundTripTime;
byte ttl;
IN_ADDR dwIPaddr;
} DECODE_RESULT;
unsigned short GenerateChecksum(unsigned short *pBuf, int iSize) {
unsigned long cksum = 0;
while (iSize > 1) {
cksum += *pBuf++;
iSize -= sizeof(unsigned short);
}
if (iSize) {
cksum += *(unsigned char *)pBuf;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (unsigned short)(~cksum);
}
int DecodeIcmpResponse(char *pBuf, int iPacketSize, DECODE_RESULT *stDecodeResult)
{
IP_HEADER *pIpHrd = (IP_HEADER *)pBuf;
int iIpHrdLen = 20;
if (iPacketSize < (int)(iIpHrdLen + sizeof(ICMP_HEADER))) {
return 0;
}
ICMP_HEADER *pIcmpHrd = (ICMP_HEADER *)(pBuf + iIpHrdLen);
unsigned short usID, usSquNo;
if (pIcmpHrd->type == ICMP_ECHO_REPLY) {
usID = pIcmpHrd->id;
usSquNo = ntohs(pIcmpHrd->seq);
}
if (usID != GetCurrentProcessId() || usSquNo != stDecodeResult->usSeqNo) {
return 0;
}
if (pIcmpHrd->type == ICMP_ECHO_REPLY) {
stDecodeResult->ttl = pIpHrd->ttl;
stDecodeResult->dwIPaddr.s_addr = pIpHrd->sourceIP;
stDecodeResult->dwRoundTripTime = GetTickCount() - stDecodeResult->dwRoundTripTime;
return 1;
}
return 0;
}
int CreateSocket(unsigned long ulDestIP) {
SOCKADDR_IN destSockAddr;
ZeroMemory(&destSockAddr, sizeof(SOCKADDR_IN));
destSockAddr.sin_family = AF_INET;
destSockAddr.sin_addr.s_addr = ulDestIP;
destSockAddr.sin_port = htons(0);
char IcmpSendBuf[DEF_ICMP_PACK_SIZE];
ICMP_HEADER * pIcmpHeader = (ICMP_HEADER *)IcmpSendBuf;
pIcmpHeader->type = ICMP_ECHO_REQUEST;
pIcmpHeader->code = 0;
pIcmpHeader->id = (unsigned short)GetCurrentProcessId();
memset(IcmpSendBuf + sizeof(ICMP_HEADER), 'E', DEF_ICMP_DATA_SIZE);
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
return FALSE;
}
SOCKET sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (sockRaw == INVALID_SOCKET)
{
printf("WSASocket() failed: %d\n", WSAGetLastError());
return FALSE;
}
int iTimeout = DEF_ICMP_TIMEOUT;
if (setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char *)&iTimeout, sizeof(iTimeout)) == SOCKET_ERROR) {
printf("设置SO_RCVTIMEO失败\n");
}
DECODE_RESULT stDecodeResult;
int usSeqNo;
for (usSeqNo = 0;usSeqNo <= 3;usSeqNo++) {
pIcmpHeader->seq = htons(usSeqNo);
pIcmpHeader->cksum = 0;
pIcmpHeader->cksum = GenerateChecksum((unsigned short *)IcmpSendBuf, sizeof(ICMP_HEADER) + DEF_ICMP_DATA_SIZE);
stDecodeResult.usSeqNo = usSeqNo;
stDecodeResult.dwRoundTripTime = GetTickCount();
if (sendto(sockRaw, IcmpSendBuf, sizeof(IcmpSendBuf), 0, (SOCKADDR*)&destSockAddr, sizeof(destSockAddr)) == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEHOSTUNREACH) {
return FALSE;
}
}
SOCKADDR_IN from;
int iFromLen = sizeof(from);
int iReadLen;
char IcmpRecvBuf[MAX_ICMP_PACKET_SIZE];
while (1) {
iReadLen = recvfrom(sockRaw, IcmpRecvBuf, MAX_ICMP_PACKET_SIZE, 0, (SOCKADDR*)&from, &iFromLen);
if (iReadLen != SOCKET_ERROR) {
if (DecodeIcmpResponse(IcmpRecvBuf, sizeof(IcmpRecvBuf), &stDecodeResult) == 1)
{
printf("来自 %s 的回复: 字节 = %d 时间 = %dms TTL = %d\n", inet_ntoa(stDecodeResult.dwIPaddr),
iReadLen - 20, stDecodeResult.dwRoundTripTime, stDecodeResult.ttl);
}
break;
}
else if (WSAGetLastError() == WSAETIMEDOUT) {
printf("time out !\n");
break;
}
else {
printf("发生未知错误!\n");
break;
}
}
}
printf("\nping complete.\n");
closesocket(sockRaw);
WSACleanup();
system("PAUSE");
return 0;
}
int main(int argc, char *argv[]) {
char arr[20];
unsigned long ulDestIP;
if (argv[1] != NULL) {
printf("ERROR!");
}
else {
printf("请输入ip地址:");
scanf("%s", arr);
ulDestIP = inet_addr(arr);
}
CreateSocket(ulDestIP);
return 0;
}