http://read.pudn.com/downloads80/sourcecode/windows/network/307147/Ping/Ping.cpp__.htm
// #pragma pack(4)
// #pragma comment(lib, "ws2_32.lib")
// #include "stdafx.h"
// #include <winsock2.h>
// #include <stdlib.h>
// #include <stdio.h>
//
// //IP报文报头结构
// typedef struct ipheader
// {
// unsigned int headlen:4; //长度
// unsigned int version:4; //版本
// unsigned char tos; //服务类型
// unsigned short totallen; //IP包总长度
// unsigned short idflag; //标识
// unsigned short flag; //标志(前3位)
// unsigned char ttl; //生命期
// unsigned char prot; //协议
// unsigned short checksum; //报头校验和
// unsigned int sourceIP; //源地址
// unsigned int destIP; //目标地址
// }IpHeader;
//
// //ICMP报文报头
// typedef struct icmpheader{
// BYTE type; //ICMP类型码,回送请求的类型码为8
// BYTE code; // 子类型码,保存与特ICMP报文类型相关的细节位置
// USHORT checksum; //校验和
// USHORT id; //ICMP报文ID号(一般用进程号作为ID)
// USHORT seq; //ICMP数据报的序列号
// ULONG timestamp;
// }IcmpHeader;
//
// #define ICMP_ECHO 8 //请求回送
// #define ICMP_ECHOREPLY 0 //请求回应
// #define ICMP_MIN 8 //ICMP包头长度(最小ICMP包长度)
//
// #define DEF_PACKET_NUMBER 4 // 发送数据报的个数
// #define STATUS_FAILED 0xFFFF //错误码
//
// #define DEF_PACKET_SIZE 32 //缺省数据报的长度
// #define MAX_PACKET 1024 //最大数据报长度
// #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
// #define xfree(p) HeapFree (GetProcessHeap(),0,(p))
//
// void fill_icmp_data(char *, int); //填充ICMP包
// USHORT checksum(USHORT *, int); //校验和函数
// int decode_resp(char *,int ,struct sockaddr_in *); //找到此数据报IP地址
//
// int main(int argc,char **argv)
// {
// WSADATA wsaData;
// SOCKET sockRaw; //原始套接字
// struct sockaddr_in dest,from; //dest:搜索目的IP;from:接收ICMP包的IP
// struct hostent *hp; //设置本地IP地址
// int bread,datasize,times;
//
// int fromlen = sizeof(from); //接收ICMP包长度
// unsigned int addr = 0; //IP地址
// int timeout = 1000; //设置读取延时
// char *dest_ip;
// char *icmp_data; //设置ICMP数据报最大可能的长度
// char *recvbuf; //接收ICMP包缓冲区
// USHORT seq_no = 0;
// int statistic = 0;
// int i;
//
// if(argc < 2) //判断输入格式是否正确
// {
// printf("输入格式错误: hping hostname\n");
// ExitProcess(STATUS_FAILED);
// }
//
// if(WSAStartup(MAKEWORD(2,1), &wsaData) != 0) //开始使用ws2_32.dll
// {
// printf("WSAStartup failed: %d\n",GetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// /**************************
// *创建原始套接字,使用WSASocket()函数
// *参数1:指定通信发生的区字段,AF_INET允许在远程主机之间通信
// *参数2:在AF_INET地址族下,有SOCK_STREAM,SOCK_DGRAM,SOCK_RAW三种套接字,这里表明使用原始套接字
// *参数3:依赖参数2,用于指定套接字所用的特定协议,这里使用ICMP协议
// *参数4:为WSAPROTOCOL_INFO位,可以置空
// *参数5:恒为0
// *参数6:标志位,为WSA_FLAG_OVERLAPPED时表明可以使用发送接收超时设置,为0时不考虑
// **************************/
// sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
// if(sockRaw == INVALID_SOCKET)
// {
// printf("WSASocket() Failed: %d",WSAGetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// /***************************************
// *函数名:setsocket
// *参数:1:设置原始套接字
// * 2:设置使用协议(TCP,UDP, ect)
// * 3:SO_SOCKET 表示使用接收超时设置,SO_SNDTIMEO表示使用发送超时设置
// ****************************************/
// bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
// if(bread == SOCKET_ERROR)
// {
// printf("failed to set recv timeout: %d",WSAGetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// timeout = 1000;
// bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
// if(bread == SOCKET_ERROR)
// {
// printf("failed to set send timeout: %d",WSAGetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// /***********************
// *函数名:memset
// *功能 :当程序使用数组和指向内存区域的指针的时候,在一段内存块中填充某个给定的值
// *注意 :第二个参数必须为0
// ***********************/
// memset(&dest,0,sizeof(dest)); //初始化dest结构
//
// if(argv[1][0] == '/'){
// hp = gethostbyname(argv[2]); //获得主机名
// if(!hp)
// {
// addr = inet_addr(argv[2]); //将一个点间隔地址转换成一个in_addr
// }
// if((!hp) && (addr == INADDR_NONE))
// {
// printf("Do not mark address: %s\n",argv[2]);
// ExitProcess(STATUS_FAILED);
// }
// }else{
// hp = gethostbyname(argv[1]); //获得主机名
// if(!hp)
// {
// addr = inet_addr(argv[1]); //将一个点间隔地址转换成一个in_addr
// }
// if((!hp) && (addr == INADDR_NONE))
// {
// printf("Do not mark address: %s\n",argv[1]);
// ExitProcess(STATUS_FAILED);
// }
// }
// if(hp != NULL)
// {
// memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
// }else
// dest.sin_addr.s_addr = addr;
// if(hp)
// {
// dest.sin_family = hp->h_addrtype;
// }else
// dest.sin_family = AF_INET;
//
// dest_ip = inet_ntoa(dest.sin_addr); //将网络地址转换成“.”点隔的字符串格式
//
//
// /*******************************
// * atoi函数原型是: int atoi( const char *string );
// * 如果输出不能确定为int类型,则返回0
// *******************************/
// if(argc > 2)
// {
// times = atoi(argv[2]);
// if(times == 0)
// times = DEF_PACKET_NUMBER; //设置ICMP数据报报文体的缺省长度
// }else times = DEF_PACKET_NUMBER;
//
// if(argc > 3)
// {
// datasize = atoi(argv[3]);
// if(datasize == 0)
// datasize = DEF_PACKET_SIZE; //设置ICMP数据报报文体的缺省长度
// if(datasize > 1024) //数据包太大
// {
// printf("Warning: data_size is too long.\n");
// datasize = DEF_PACKET_SIZE;
// }
// }else datasize = DEF_PACKET_SIZE;
//
// datasize += sizeof(IcmpHeader); //加上ICMP头部的长度
// icmp_data = (char*)xmalloc(MAX_PACKET);
// recvbuf = (char*)xmalloc(MAX_PACKET);
// if(!icmp_data)
// {
// printf("HeapAlloc failed %d\n",GetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// memset(icmp_data,0,MAX_PACKET); //将数据报清空初始化
// fill_icmp_data(icmp_data,datasize); //填充ICMP数据报
//
// //显示提示信息
// printf("\nPinging %s .....\n\n",dest_ip);
//
// for(i=0;i<times;i++)
// {
// int bwrote;
// if(argv[1][0] == '/'){ //处理 /t 参数
// if(argv[1][1] == 't')
// i=0;
// else{
// printf("参数错误!\n");
// return 1;
// }
// }
// ((IcmpHeader*)icmp_data)->checksum = 0; //先将校验和置0
// ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
// ((IcmpHeader*)icmp_data)->seq = seq_no++;
//
// //计算校验和后填入
// ((IcmpHeader*)icmp_data)->checksum = checksum((USHORT*)icmp_data,datasize);
// //发送数据报
// bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
// if(bwrote == SOCKET_ERROR)
// {
// if(WSAGetLastError() == WSAETIMEDOUT)
// {
// printf("REQUEST time out\n");
// continue;
// }
// printf("sendto failed: %d\n",WSAGetLastError());
// ExitProcess(STATUS_FAILED);
// }
// if(bwrote < datasize)
// {
// printf("Wrote %d bytes\n",bwrote);
// ExitProcess(STATUS_FAILED);
// }
// //接收数据报
// bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);
// if(bread == SOCKET_ERROR)
// {
// if(WSAGetLastError() == WSAETIMEDOUT)
// {
// printf("REQUEST timeOut.\n");
// continue;
// }
// printf("recvfrom failed: %d",WSAGetLastError());
// ExitProcess(STATUS_FAILED);
// }
//
// if(!decode_resp(recvbuf,bread,&from))
// statistic++; //成功接收的数目
// Sleep(1000);
// }
//
// //显示统计信息
// printf("\nPinging statistics for %s :\n",dest_ip);
// printf(" Packets: Sent = %d, Received = %d, Lost = %d (%2.0f%% loss)\n",times,
// statistic,(times-statistic),(float)(times-statistic)/times*100);
// WSACleanup();
// return 0;
// }
//
//
// void fill_icmp_data(char * icmp_data, int datasize)
// {
// IcmpHeader *icmphdr;
// char *datapart;
//
// icmphdr = (IcmpHeader*)icmp_data;
//
// icmphdr->type = ICMP_ECHO; //设置类型信息
// icmphdr->code = 0;
// icmphdr->id = (USHORT)GetCurrentProcessId(); //设置其ID号为当前进程的ID号
// icmphdr->seq = 0;
// icmphdr->checksum = 0;
//
// datapart = icmp_data + sizeof(IcmpHeader); //计算出ICMP数据报的数据部分
// memset(datapart,'E',datasize - sizeof(IcmpHeader)); //填入数据
// }
//
// USHORT checksum(USHORT *buffer,int size) //计算校验和
// {
// unsigned long cksum = 0;
// while(size > 1)
// {
// cksum += *buffer++;
// size -= sizeof(USHORT);
// }
// if(size){
// cksum += *(UCHAR*)buffer;
// }
//
// cksum = (cksum >> 16) + (cksum & 0xffff);
// cksum += (cksum >> 16);
// return (USHORT)(~cksum);
// }
//
// int decode_resp(char *buf,int bytes,struct sockaddr_in *from)
// {
// IcmpHeader *icmphdr;
// IpHeader *iphdr;
// unsigned short iphdrlen;
//
// iphdr = (IpHeader *)buf;
// iphdrlen = (iphdr->headlen) * 4; //IP报头的长度
// icmphdr = (IcmpHeader*)(buf+iphdrlen); //跳过IP报头
//
// if(bytes < iphdrlen+ICMP_MIN)
// {
// printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
// //return 1; //数据包太短,丢弃
// }
//
// if(icmphdr->type != ICMP_ECHOREPLY)
// {
// printf("non-echo type %d recvd\n",icmphdr->type);
// return 1; //不是回送响应(ping应答),丢弃
// }
//
// if(icmphdr->id != (USHORT)GetCurrentProcessId())
// {
// printf("someone else's packet!\n");
// return 1; //ID号不符,丢弃
// }
// printf("REPLY FROM %s ",inet_ntoa(from->sin_addr));
// printf("%d bytes from %s",bytes,inet_ntoa(from->sin_addr));
// printf(" icmp_seq = %d. ",icmphdr->seq);
// printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);
// printf("\n");
// return 0;
// }
第二种
// #include <StdAfx.h>
// #include <stdlib.h>
// #include <stdio.h>
// #include <WINSOCK2.H>
// #include <windows.h>
//
//
// #include <ws2tcpip.h> //IP_TTL
// #pragma comment(lib,"ws2_32.lib")
// //ICMP首部结构体
// typedef struct tagICMPHEADER
// {
// unsigned char type;//类型
// unsigned char code;//代码
// unsigned short checknum;//检验和
// unsigned short id;//标识符
// unsigned short seq_num;//序列号
// }ICMPHEADER;
// //IP首部结构体
// typedef struct _ip_hdr
// {
// unsigned char ihl:4; //首部长度
// unsigned char version:4; //版本
// unsigned char tos; //服务类型
// unsigned short tot_len; //总长度
// unsigned short id; //标志
// unsigned short frag_off; //分片偏移
// unsigned char ttl; //生存时间
// unsigned char protocol; //协议
// unsigned short chk_sum; //检验和
// struct in_addr srcaddr; //源IP地址
// struct in_addr dstaddr; //目的IP地址
// }IPHEADER;
//
//
// //计算检验和
// unsigned short checksum(unsigned short *buffer, int size)
// {
// unsigned long cksum = 0; // 将所有的16数相加
// while (size > 1)
// {
// cksum += *buffer++;
// size -= sizeof(unsigned short);
// }
// if (size) //加上最后一个BYTE
// {
// cksum += *(unsigned char*)buffer;
// }
// while (cksum>>16)
// {
// cksum = (cksum & 0xffff) + (cksum >> 16);
// }
// return (unsigned short)~cksum;
// }
//
//
// int main()
// {
// WSADATA wsadata;
// if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
// {
// printf("初始化socket dll失败\n");
// return 1;
// }
// //设置ICMP首部内容
// ICMPHEADER icmp_hdr;
// icmp_hdr.type=8;
// icmp_hdr.code=0;
// icmp_hdr.checknum=0;
// icmp_hdr.id=(unsigned short)GetCurrentProcessId();
// icmp_hdr.seq_num=0;
// //计算检验和
// icmp_hdr.checknum=checksum((unsigned short*)&icmp_hdr,sizeof(icmp_hdr));
// //设置原始套接字
// SOCKET sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,0);
// if(INVALID_SOCKET==sock)
// {
// printf("创建socket失败\n");
// WSACleanup();
// return 1;
// }
// int ttl=255;
// //设置TTL为255
// if(setsockopt(sock,IPPROTO_IP,IP_TTL,(const char*)&ttl,sizeof(ttl))==SOCKET_ERROR)
// {
// printf("set TTL error!\n");
// WSACleanup();
// return 2;
// }
// //目标地址
// SOCKADDR_IN Dest_addr;
// memset(&Dest_addr,0,sizeof(Dest_addr));
// Dest_addr.sin_family=AF_INET;
// Dest_addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
// //发送ICMP请求报文
// int status=sendto(sock,(const char*)&icmp_hdr,sizeof(icmp_hdr),0,(SOCKADDR*)&Dest_addr,sizeof(Dest_addr));
// if(SOCKET_ERROR==status)
// {
// printf("sent error!\n");
// shutdown(sock,SD_BOTH);
// closesocket(sock);
// WSACleanup();
// return 3;
// }
// int size=60+sizeof(ICMPHEADER);
// char *buffer=(char*)malloc(size);
// memset(buffer,0,size);
// int des=sizeof(SOCKADDR_IN);
// //接受ICMP回应报文并分析
// while (true)
// {
// recvfrom(sock,buffer,size,0,(SOCKADDR*)&Dest_addr,&des);
// ICMPHEADER *p=(ICMPHEADER*)((char*)buffer+((IPHEADER*)buffer)->ihl*4);
// if(p->type==0)
// {
// if(p->id==icmp_hdr.id)
// {
// printf("ping %s成功\n",inet_ntoa(Dest_addr.sin_addr));
// break;
// }
// }
// else
// {
// printf("ping %s不成功\n",inet_ntoa(Dest_addr.sin_addr));
// break;
// }
// }
// shutdown(sock,SD_BOTH);
// closesocket(sock);
// WSACleanup();
// return 0;
// }