ping
用Raw Socket来实现ICMP_ECHO协议。
#include <windows.h>
#include <winsock.h>#pragma comment(lib, "ws2_32")
typedef struct _ihdr {
u_char i_type, i_code;
u_short i_cksum,i_id, i_seq;
} IcmpHeader;u_short checksum(u_short *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 APIENTRY WinMain(HINSTANCE,HINSTANCE,LPSTR,int) {
WSADATA wsaData;
SOCKET sockRaw = INVALID_SOCKET;
struct sockaddr_in dest,from;
char icmp_data[10], recvbuf[1024];
unsigned int addr=0;
int fromlen = sizeof(from);
int timeout = 3000; //ms
int count = 3;
struct hostent* host;
char szDestHost[] = "www.sinzy.net";WSAStartup(MAKEWORD(2,1),&wsaData) ;
if(inet_addr(szDestHost)==INADDR_NONE) {
host=gethostbyname(szDestHost);
} else {
addr=inet_addr(szDestHost);
host=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(host == NULL) {
MessageBox(NULL, "Not Resolved!", szDestHost, MB_OK);
} else {
sockRaw = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = *((unsigned long*)host->h_addr);
memset(icmp_data,0,sizeof(icmp_data)); //clear icmp_data.
((IcmpHeader*)icmp_data)->i_type = 8; //ICMP_ECHO
((IcmpHeader*)icmp_data)->i_code = 0;
((IcmpHeader*)icmp_data)->i_id = (u_short)GetCurrentProcessId();
((IcmpHeader*)icmp_data)->i_seq = 0;for(int k=0; k < count; k ++) {
((IcmpHeader*)icmp_data)->i_cksum = 0;
((IcmpHeader*)icmp_data)->i_seq ++;
((IcmpHeader*)icmp_data)->i_cksum=checksum((u_short*)icmp_data,8);
sendto(sockRaw,icmp_data,8,0,(struct sockaddr*)&dest,sizeof(dest));
int bread=recvfrom(sockRaw,recvbuf,1024,0,(struct sockaddr*)&from, &fromlen);
if(bread != SOCKET_ERROR){
break;
}
}
closesocket(sockRaw);
sockRaw = INVALID_SOCKET;
MessageBox(NULL, (k==count)?"Failed!":"Succeeded!", szDestHost, MB_OK);
}WSACleanup();
return 0;
}