该代码由网上的文章“微软ping程序源代码完整版”修改而来。该文实现一个完整的ping命令,为方便在其他程序中调用,在此将其封装成一个独立的函数。
BOOL Ping(char *strIP,int nTimeout,DWORD *dwErr);
strIP:目标ip;
nTimeout:超时时间,以ms为单位。
dwErr:失败时的错误代码
调用示例如下:
Ping("192.168.1.131",5000,&err);
代码如下:
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8
/* The IP header */
#pragma pack(4)
typedef struct iphdr {
unsigned int h_len:4; // length of the header
unsigned int version:4; // Version of IP
unsigned char tos; // Type of service
unsigned short total_len; // total length of the packet
unsigned short ident; // unique identifier
unsigned short frag_and_flags; // flags
unsigned char ttl;
unsigned char proto; // protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum
unsigned int sourceIP;
unsigned int destIP;
}IpHeader;
// ICMP header
typedef struct icmphdr {
BYTE i_type;
BYTE i_code; /* type sub code */
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
/* This is not the std header, but we reserve space for time */
ULONG timestamp;
}IcmpHeader;
#define DEF_PACKET_SIZE 8
#define MAX_PACKET 1024
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);
}
BOOL Ping(char *strIP,int nTimeout,DWORD *dwErr)
{
SOCKET sockRaw;
BOOL bRet = FALSE;
sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);
if (sockRaw != INVALID_SOCKET)
{
setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&nTimeout, sizeof(nTimeout));
setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&nTimeout, sizeof(nTimeout));
struct sockaddr_in dest;
memset(&dest,0,sizeof(dest));
dest.sin_addr.s_addr = inet_addr(strIP);
dest.sin_family = AF_INET;
char buf[MAX_PACKET] = {0};
IcmpHeader *icmp_hdr =(IcmpHeader*) buf;
icmp_hdr->i_type = ICMP_ECHO;
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum = 0;
icmp_hdr->i_seq = 0;
memset(buf + sizeof(IcmpHeader),'E', DEF_PACKET_SIZE);
icmp_hdr->i_cksum = checksum((USHORT*)buf,DEF_PACKET_SIZE + sizeof(IcmpHeader));
if ( sendto(sockRaw,buf,DEF_PACKET_SIZE + sizeof(IcmpHeader),0,(struct sockaddr*)&dest,sizeof(dest)) != SOCKET_ERROR)
{
struct sockaddr_in from;
int fromlen = sizeof(sockaddr_in);
int nRecv = recvfrom(sockRaw,buf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);
if (nRecv != SOCKET_ERROR)
{
IpHeader *iphdr;
IcmpHeader *icmphdr;
unsigned short iphdrlen;
iphdr = (IpHeader *)buf;
iphdrlen = (iphdr->h_len) * 4 ;
if (nRecv >= iphdrlen + ICMP_MIN)
{
icmphdr = (IcmpHeader*)(buf + iphdrlen);
if (icmphdr->i_type == ICMP_ECHOREPLY && icmphdr->i_id == (USHORT)GetCurrentProcessId())
{
bRet = TRUE;
}
}
}
}
}
if (!bRet)
{
*dwErr = WSAGetLastError();
}
return bRet;
}
int main(int argc, char **argv)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,1),&wsaData);
DWORD err = 0;
BOOL ret = Ping("192.168.1.131",5000,&err);
printf("ping %d %d\n",ret,err);
WSACleanup();
return 0;
}