自己寫的一個(gè)ping程序
Posted on 2009-09-15 11:16 亂78糟 閱讀(6535) 評(píng)論(12) 編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程以前學(xué)習(xí)ICMP協(xié)議時(shí)候?qū)懙囊粋€(gè)模仿windows自帶的ping程序,今天翻代碼看到了,貼上來供大家拍磚。
2010-12-15日更新補(bǔ)充:這段代碼獲取的是第一個(gè)活動(dòng)網(wǎng)卡IP來發(fā)送ICMP報(bào)文,如果有多個(gè)網(wǎng)卡,例如插網(wǎng)線和wifi網(wǎng)卡同時(shí)開,那么就由插網(wǎng)線的網(wǎng)卡發(fā)送,如何讓wifi網(wǎng)卡發(fā)送呢?很簡(jiǎn)單,加一個(gè)-p [bindLocalIP]參數(shù)就可以了,bindLocalIP就是指定綁定了某個(gè)IP網(wǎng)卡發(fā)送ICMP報(bào)文,而不是由gethostname來獲取,因?yàn)楹芎?jiǎn)單,所以代碼就懶得修改了,畢竟是多年前的代碼了。
本人已經(jīng)在2K(32),XP(32),VISTA(64),WIN7(32)下測(cè)試過,一切正常。
2010-12-15日更新補(bǔ)充:這段代碼獲取的是第一個(gè)活動(dòng)網(wǎng)卡IP來發(fā)送ICMP報(bào)文,如果有多個(gè)網(wǎng)卡,例如插網(wǎng)線和wifi網(wǎng)卡同時(shí)開,那么就由插網(wǎng)線的網(wǎng)卡發(fā)送,如何讓wifi網(wǎng)卡發(fā)送呢?很簡(jiǎn)單,加一個(gè)-p [bindLocalIP]參數(shù)就可以了,bindLocalIP就是指定綁定了某個(gè)IP網(wǎng)卡發(fā)送ICMP報(bào)文,而不是由gethostname來獲取,因?yàn)楹芎?jiǎn)單,所以代碼就懶得修改了,畢竟是多年前的代碼了。
本人已經(jīng)在2K(32),XP(32),VISTA(64),WIN7(32)下測(cè)試過,一切正常。
/*******************************************************************
程序: myping
功能: 模擬ping命令
O/S : WINDOWS 98或更高版本
作者: 嚴(yán)政
時(shí)間: 2007.8.14
版本變更:
V1.0.0 2007.8.14 初始版本,實(shí)現(xiàn)了基本的ping功能
說明:
這是開源代碼,你可以隨意拷貝使用。如果你有好的建議或
意見,發(fā)E-mail至: [ yzljlss@126.com ]討論。
*******************************************************************/
#include <stdio.h>
#include <WINSOCK2.H>
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"Ws2_32.lib")
#define SIO_RECALL _WSAIOW(IOC_VENDOR,1)
#define MAX_HOSTNAME_LEN 256
sockaddr_in LocalAddr,SendAddr,destAddr;
SOCKET sock;
struct hostent FAR *pHostent, *pTmp;
int total = 4;//發(fā)送ping報(bào)文次數(shù),默認(rèn)為4次
int seconds = 0;//發(fā)送時(shí)間間隔
bool hostToIp = false;//-a 將目標(biāo)的機(jī)器標(biāo)識(shí)轉(zhuǎn)換為ip地址
bool pingforever = false;//-t 若使用者不人為中斷會(huì)不斷的ping下去
bool isCount = false;//-c count 要求ping命令連續(xù)發(fā)送count個(gè)數(shù)據(jù)包
bool isSimple = false;//-q ping只在開始和結(jié)束時(shí)打印一些概要信息
char FAR name[MAX_HOSTNAME_LEN];
char destIP[16];//目標(biāo)IP
typedef struct _ping
{
UCHAR i_type;//8位類型
UCHAR i_code;//8位代碼
USHORT i_chksum;//16位ICMP校驗(yàn)和
USHORT i_identify;//16位標(biāo)志位
USHORT i_seqnum;//16位序號(hào)
ULONG i_timestamp;//32位時(shí)間戳
UCHAR i_data[32];//32BYTE選項(xiàng)數(shù)據(jù)
}PingHeader,*pPingHeader;
typedef struct _ipHeader//IP頭部,總長(zhǎng)度20字節(jié)
{
#if LITTLEENDIAN
UCHAR IpHlen:4, //4位首部長(zhǎng)度
IpVer :4; //4位IP版本號(hào)
#else
UCHAR IpVer :4, //4位IP版本號(hào)
IpHlen:4; //4位首部長(zhǎng)度
#endif
UCHAR IpTos;//8服務(wù)類型
USHORT IpTlen;//總長(zhǎng)度
USHORT IpId;//標(biāo)志
USHORT FlagsOff;//分片偏移
UCHAR IpTtl;//生存時(shí)間
UCHAR IpProto;//協(xié)議
USHORT ChkSum;//檢驗(yàn)和
struct in_addr SourIp;//源IP地址
struct in_addr DestIp; //目的IP地址
} IpHeader,*pIpHeader;
//求校驗(yàn)和
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);
}
//幫助信息
void help()
{
printf("==========================[ myping V1.0.0 ]============================ ");
printf(" 用法: myping [-a] [-t] [-c count] [-i seconds] [-q] [-h] target_IP ");
printf("參數(shù): ");
printf(" -a 將目標(biāo)的機(jī)器標(biāo)識(shí)轉(zhuǎn)換為ip地址 ");
printf(" 建議: ping遠(yuǎn)程主機(jī)時(shí)不要添加此參數(shù),否則速度較慢 ");
printf(" -t 若使用者不人為中斷會(huì)不斷的ping下去 ");
printf(" -c count 要求ping命令連續(xù)發(fā)送count個(gè)數(shù)據(jù)包 ");
printf(" -i seconds 在兩次數(shù)據(jù)包發(fā)送之間間隔一定的秒數(shù) ");
printf(" -q myping只在開始和結(jié)束時(shí)打印一些概要信息 ");
printf(" -h 幫助信息 ");
printf("例如: myping -a -i 1 -c 10 192.168.0.100 ");
printf("=========================[ By 嚴(yán)政 07.8.14 ]=========================== ");
}
//發(fā)送,解析PING報(bào)文
int funPing()
{
unsigned long i,
totalrecv=0;//收到包的數(shù)目
unsigned long addr, timestamp,
maxtime = 0,//最大延遲
mintime = 0;//最小延遲
PingHeader ping,*ping_hdr;
char recv_buff[65535];
char szDestIP[16];
int recvLen;
pIpHeader ip_hdr;
SendAddr.sin_family = AF_INET;
SendAddr.sin_addr.s_addr = inet_addr(destIP);
if(hostToIp)
{
memset(name, 0, MAX_HOSTNAME_LEN);
//獲取ping對(duì)象主機(jī)名
addr = inet_addr(destIP);
pHostent = gethostbyaddr((char *)&addr, sizeof(destIP) , AF_INET);
if(pHostent == NULL)
{
//printf("fail to get host name: %d ",WSAGetLastError());
fprintf(stdout, "Ping %s with 32 bytes of datas: ",destIP);
}
else
fprintf(stdout, "Ping %s[ %s ] with 32 bytes of datas: ", pHostent->h_name, destIP);
}
else
fprintf(stdout, "Ping %s with 32 bytes of datas: ",destIP);
for(i=0;;i++)
{
if(!pingforever)
{
if(i >= (unsigned long)total)//達(dá)到發(fā)送次數(shù)
break;
}
//填充PING報(bào)文
ping.i_type = 8;
ping.i_code = 0;
ping.i_seqnum = (USHORT)i;
ping.i_identify = (unsigned short)GetCurrentProcessId();
ping.i_timestamp = (unsigned long)::GetTickCount();
for(int j=0;j < 32; j++)
ping.i_data[i] = (UCHAR)('a'+j);
ping.i_chksum = 0;
//計(jì)算校驗(yàn)和
ping.i_chksum = checksum((unsigned short*)&ping,sizeof(ping));
//printf("checksum=%d ",ping.i_chksum);
if(sendto(sock, (char*)&ping, sizeof(ping),0, (struct sockaddr*)&SendAddr, sizeof(SendAddr)) == SOCKET_ERROR)
{
printf("Send ping packet error: %d ",WSAGetLastError());
return -1;
}
memset(recv_buff, 0, 1024);
int len = sizeof(destAddr);
if((recvLen = recvfrom(sock, recv_buff, sizeof(recv_buff), 0, (struct sockaddr*)&destAddr, &len)) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(err != 10060)//超時(shí)錯(cuò)誤不返回
{
printf("recv data error: %d ",err);
return -1;
}
else if(!isSimple)
fprintf(stdout, "請(qǐng)求超時(shí). ");
}
if(recvLen > 0)
{
//處理接收的IP報(bào)文,解析PING應(yīng)答報(bào)文
ip_hdr = (pIpHeader)recv_buff;
memcpy(szDestIP, inet_ntoa(ip_hdr->SourIp), 16);
if(ip_hdr->IpProto == IPPROTO_ICMP && !strcmp(szDestIP, destIP))//處理來自PING對(duì)象且是ICMP的報(bào)文
{
ping_hdr = (pPingHeader)(recv_buff + sizeof(unsigned long)*ip_hdr->IpHlen);
// fprintf(stdout,"ping_hdr.i_type=%02X ",ping_hdr->i_type);
// fprintf(stdout,"ping_hdr.i_code=%02X ",ping_hdr->i_code);
// fprintf(stdout,"ping_hdr.i_seqnum=%04X ",ping_hdr->i_seqnum);
// fprintf(stdout,"ping_hdr.i_identify=%04X ",ping_hdr->i_identify);
// fprintf(stdout,"ping_hdr.timestamp=%08X ",ping_hdr->i_timestamp);
//應(yīng)答報(bào)文
if(ping_hdr->i_type == 0)
{
//計(jì)算延遲時(shí)間
timestamp = (unsigned long)::GetTickCount();
timestamp -= ping_hdr->i_timestamp;
if(i == 0)
mintime = timestamp;
maxtime = (timestamp > maxtime) ? timestamp : maxtime;//最大延遲時(shí)間
mintime = (timestamp < mintime) ? timestamp : mintime;//最小延遲時(shí)間
if(timestamp == 0)
timestamp = 1;
if(!isSimple)
fprintf(stdout, "Reply from %s: bytes=%d time<%dms TTL=%d ", destIP,
sizeof(ping_hdr->i_data), timestamp, ip_hdr->IpTtl );
//收到包的數(shù)目
totalrecv++;
}
if(ping_hdr->i_type == 3)
{
fprintf(stdout, "目的不可達(dá)");
switch(ping_hdr->i_code)
{
case 0:
fprintf(stdout, "(網(wǎng)絡(luò)不可達(dá)) ");
break;
case 1:
fprintf(stdout, "(主機(jī)不可達(dá)) ");
break;
case 2:
fprintf(stdout, "(協(xié)議不可達(dá)) ");
break;
case 3:
fprintf(stdout, "(端口不可達(dá)) ");
break;
default:
break;
}
}
if(ping_hdr->i_type == 5)
{
if(ping_hdr->i_code == 0)
fprintf(stdout, "對(duì)網(wǎng)絡(luò)重定向. ");
if(ping_hdr->i_code == 1)
fprintf(stdout, "對(duì)主機(jī)重定向. ");
}
}
}
Sleep(seconds);
}//end for
//計(jì)算ping統(tǒng)計(jì)信息
fprintf(stdout, " Ping %s 的統(tǒng)計(jì)信息: ",destIP);
fprintf(stdout, " 包: 發(fā)送 = %d, 收到 = %d, 丟失 = %d (丟失率: %.0f%%) ",
i, totalrecv, (i-totalrecv), ((float)(i-totalrecv))/i*100 );
if(totalrecv != 0)//沒收到包打印路由信息無意義
{
fprintf(stdout, "近似路由時(shí)間(毫秒): ");
fprintf(stdout, " 最大 = %dms, 最小 = %dms, 平均 = %dms ", maxtime, mintime, (maxtime+mintime)/2);
}
return 0;
}
int main(int argc, char* argv[])
{
DWORD lpvBuffer = 1;
DWORD lpcbBytesReturned = 0;
int nNetTimeout=3000;//超時(shí)3秒
//初始化套結(jié)字
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != 0)
{
printf("fail to init socket: %d",WSAGetLastError());
return -1;
}
//創(chuàng)建套結(jié)字
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int));
if(sock == SOCKET_ERROR)
{
printf("fail to create socket: %d",WSAGetLastError());
return -1;
}
//獲取本機(jī)IP
if(gethostname(name, MAX_HOSTNAME_LEN))
{
printf("get host name error: %d",WSAGetLastError());
return -1;
}
pHostent = (struct hostent *)malloc(sizeof(struct hostent));
pTmp = pHostent;
pHostent = gethostbyname(name);
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_port = htons(0);
memcpy(&LocalAddr.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);
//bind socket
if(bind(sock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR)
{
printf("bind error: %d",WSAGetLastError());
return -1;
}
/*
//置網(wǎng)卡為混雜模式
//在這個(gè)ping程序中,不能將網(wǎng)卡置于混雜模式,否則接收的報(bào)文包括自己發(fā)送的報(bào)文 (^_^)
if(WSAIoctl(sock, SIO_RECALL, &lpvBuffer ,sizeof(lpvBuffer), NULL, 0,
&lpcbBytesReturned, NULL, NULL) == SOCKET_ERROR)
{
printf("WSAIoctl(
) error: %d",WSAGetLastError());
return -1;
}
*/
//命令行解析
if(argc < 2)
{
printf("必須輸入ping參數(shù)! ");
help();
return -1;
}
else
{
for(int i=1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch( (tolower(argv[i][1])) )
{
case 'a':
hostToIp = true;
break;
case 't':
pingforever = true;
break;
case 'h':
help();
return -1;
break;
case 'q'://ping只在開始和結(jié)束時(shí)打印一些概要信息
isSimple = true;
break;
case 'c':
{
if( *(argv[i]+3) > '9' || *(argv[i]+3) < '0' )
{
printf("ping次數(shù)錯(cuò)誤參數(shù)! ");
help();
return -1;
}
//發(fā)送報(bào)文次數(shù)
total = atoi(argv[++i]);
break;
}
case 'i'://設(shè)置發(fā)送報(bào)文時(shí)間差
{
if( *(argv[i]+3) > '9' || *(argv[i]+3) < '0' )
{
printf("時(shí)間錯(cuò)誤參數(shù)! ");
help();
return -1;
}
//發(fā)送報(bào)文次數(shù)
seconds = atoi(argv[++i]) * 1000;
break;
}
default:
break;
}//end switch
}//end if
}//end for
if( (argv[argc-1][0]) > '9' || (argv[argc-1][0]) < '0' )
{
printf("目的IP錯(cuò)誤!請(qǐng)確認(rèn)最后一個(gè)參數(shù)是目的IP. ");
help();
return -1;
}
memcpy(destIP, argv[argc-1], strlen(argv[argc-1]));
}
//發(fā)送ping報(bào)文
funPing();
free(pTmp);
closesocket(sock);
WSACleanup();
return 0;
}
程序: myping
功能: 模擬ping命令
O/S : WINDOWS 98或更高版本
作者: 嚴(yán)政
時(shí)間: 2007.8.14
版本變更:
V1.0.0 2007.8.14 初始版本,實(shí)現(xiàn)了基本的ping功能
說明:
這是開源代碼,你可以隨意拷貝使用。如果你有好的建議或
意見,發(fā)E-mail至: [ yzljlss@126.com ]討論。
*******************************************************************/
#include <stdio.h>
#include <WINSOCK2.H>
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"Ws2_32.lib")
#define SIO_RECALL _WSAIOW(IOC_VENDOR,1)
#define MAX_HOSTNAME_LEN 256
sockaddr_in LocalAddr,SendAddr,destAddr;
SOCKET sock;
struct hostent FAR *pHostent, *pTmp;
int total = 4;//發(fā)送ping報(bào)文次數(shù),默認(rèn)為4次
int seconds = 0;//發(fā)送時(shí)間間隔
bool hostToIp = false;//-a 將目標(biāo)的機(jī)器標(biāo)識(shí)轉(zhuǎn)換為ip地址
bool pingforever = false;//-t 若使用者不人為中斷會(huì)不斷的ping下去
bool isCount = false;//-c count 要求ping命令連續(xù)發(fā)送count個(gè)數(shù)據(jù)包
bool isSimple = false;//-q ping只在開始和結(jié)束時(shí)打印一些概要信息
char FAR name[MAX_HOSTNAME_LEN];
char destIP[16];//目標(biāo)IP
typedef struct _ping
{
UCHAR i_type;//8位類型
UCHAR i_code;//8位代碼
USHORT i_chksum;//16位ICMP校驗(yàn)和
USHORT i_identify;//16位標(biāo)志位
USHORT i_seqnum;//16位序號(hào)
ULONG i_timestamp;//32位時(shí)間戳
UCHAR i_data[32];//32BYTE選項(xiàng)數(shù)據(jù)
}PingHeader,*pPingHeader;
typedef struct _ipHeader//IP頭部,總長(zhǎng)度20字節(jié)
{
#if LITTLEENDIAN
UCHAR IpHlen:4, //4位首部長(zhǎng)度
IpVer :4; //4位IP版本號(hào)
#else
UCHAR IpVer :4, //4位IP版本號(hào)
IpHlen:4; //4位首部長(zhǎng)度
#endif
UCHAR IpTos;//8服務(wù)類型
USHORT IpTlen;//總長(zhǎng)度
USHORT IpId;//標(biāo)志
USHORT FlagsOff;//分片偏移
UCHAR IpTtl;//生存時(shí)間
UCHAR IpProto;//協(xié)議
USHORT ChkSum;//檢驗(yàn)和
struct in_addr SourIp;//源IP地址
struct in_addr DestIp; //目的IP地址
} IpHeader,*pIpHeader;
//求校驗(yàn)和
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);
}
//幫助信息
void help()
{
printf("==========================[ myping V1.0.0 ]============================ ");
printf(" 用法: myping [-a] [-t] [-c count] [-i seconds] [-q] [-h] target_IP ");
printf("參數(shù): ");
printf(" -a 將目標(biāo)的機(jī)器標(biāo)識(shí)轉(zhuǎn)換為ip地址 ");
printf(" 建議: ping遠(yuǎn)程主機(jī)時(shí)不要添加此參數(shù),否則速度較慢 ");
printf(" -t 若使用者不人為中斷會(huì)不斷的ping下去 ");
printf(" -c count 要求ping命令連續(xù)發(fā)送count個(gè)數(shù)據(jù)包 ");
printf(" -i seconds 在兩次數(shù)據(jù)包發(fā)送之間間隔一定的秒數(shù) ");
printf(" -q myping只在開始和結(jié)束時(shí)打印一些概要信息 ");
printf(" -h 幫助信息 ");
printf("例如: myping -a -i 1 -c 10 192.168.0.100 ");
printf("=========================[ By 嚴(yán)政 07.8.14 ]=========================== ");
}
//發(fā)送,解析PING報(bào)文
int funPing()
{
unsigned long i,
totalrecv=0;//收到包的數(shù)目
unsigned long addr, timestamp,
maxtime = 0,//最大延遲
mintime = 0;//最小延遲
PingHeader ping,*ping_hdr;
char recv_buff[65535];
char szDestIP[16];
int recvLen;
pIpHeader ip_hdr;
SendAddr.sin_family = AF_INET;
SendAddr.sin_addr.s_addr = inet_addr(destIP);
if(hostToIp)
{
memset(name, 0, MAX_HOSTNAME_LEN);
//獲取ping對(duì)象主機(jī)名
addr = inet_addr(destIP);
pHostent = gethostbyaddr((char *)&addr, sizeof(destIP) , AF_INET);
if(pHostent == NULL)
{
//printf("fail to get host name: %d ",WSAGetLastError());
fprintf(stdout, "Ping %s with 32 bytes of datas: ",destIP);
}
else
fprintf(stdout, "Ping %s[ %s ] with 32 bytes of datas: ", pHostent->h_name, destIP);
}
else
fprintf(stdout, "Ping %s with 32 bytes of datas: ",destIP);
for(i=0;;i++)
{
if(!pingforever)
{
if(i >= (unsigned long)total)//達(dá)到發(fā)送次數(shù)
break;
}
//填充PING報(bào)文
ping.i_type = 8;
ping.i_code = 0;
ping.i_seqnum = (USHORT)i;
ping.i_identify = (unsigned short)GetCurrentProcessId();
ping.i_timestamp = (unsigned long)::GetTickCount();
for(int j=0;j < 32; j++)
ping.i_data[i] = (UCHAR)('a'+j);
ping.i_chksum = 0;
//計(jì)算校驗(yàn)和
ping.i_chksum = checksum((unsigned short*)&ping,sizeof(ping));
//printf("checksum=%d ",ping.i_chksum);
if(sendto(sock, (char*)&ping, sizeof(ping),0, (struct sockaddr*)&SendAddr, sizeof(SendAddr)) == SOCKET_ERROR)
{
printf("Send ping packet error: %d ",WSAGetLastError());
return -1;
}
memset(recv_buff, 0, 1024);
int len = sizeof(destAddr);
if((recvLen = recvfrom(sock, recv_buff, sizeof(recv_buff), 0, (struct sockaddr*)&destAddr, &len)) == SOCKET_ERROR)
{
int err = WSAGetLastError();
if(err != 10060)//超時(shí)錯(cuò)誤不返回
{
printf("recv data error: %d ",err);
return -1;
}
else if(!isSimple)
fprintf(stdout, "請(qǐng)求超時(shí). ");
}
if(recvLen > 0)
{
//處理接收的IP報(bào)文,解析PING應(yīng)答報(bào)文
ip_hdr = (pIpHeader)recv_buff;
memcpy(szDestIP, inet_ntoa(ip_hdr->SourIp), 16);
if(ip_hdr->IpProto == IPPROTO_ICMP && !strcmp(szDestIP, destIP))//處理來自PING對(duì)象且是ICMP的報(bào)文
{
ping_hdr = (pPingHeader)(recv_buff + sizeof(unsigned long)*ip_hdr->IpHlen);
// fprintf(stdout,"ping_hdr.i_type=%02X ",ping_hdr->i_type);
// fprintf(stdout,"ping_hdr.i_code=%02X ",ping_hdr->i_code);
// fprintf(stdout,"ping_hdr.i_seqnum=%04X ",ping_hdr->i_seqnum);
// fprintf(stdout,"ping_hdr.i_identify=%04X ",ping_hdr->i_identify);
// fprintf(stdout,"ping_hdr.timestamp=%08X ",ping_hdr->i_timestamp);
//應(yīng)答報(bào)文
if(ping_hdr->i_type == 0)
{
//計(jì)算延遲時(shí)間
timestamp = (unsigned long)::GetTickCount();
timestamp -= ping_hdr->i_timestamp;
if(i == 0)
mintime = timestamp;
maxtime = (timestamp > maxtime) ? timestamp : maxtime;//最大延遲時(shí)間
mintime = (timestamp < mintime) ? timestamp : mintime;//最小延遲時(shí)間
if(timestamp == 0)
timestamp = 1;
if(!isSimple)
fprintf(stdout, "Reply from %s: bytes=%d time<%dms TTL=%d ", destIP,
sizeof(ping_hdr->i_data), timestamp, ip_hdr->IpTtl );
//收到包的數(shù)目
totalrecv++;
}
if(ping_hdr->i_type == 3)
{
fprintf(stdout, "目的不可達(dá)");
switch(ping_hdr->i_code)
{
case 0:
fprintf(stdout, "(網(wǎng)絡(luò)不可達(dá)) ");
break;
case 1:
fprintf(stdout, "(主機(jī)不可達(dá)) ");
break;
case 2:
fprintf(stdout, "(協(xié)議不可達(dá)) ");
break;
case 3:
fprintf(stdout, "(端口不可達(dá)) ");
break;
default:
break;
}
}
if(ping_hdr->i_type == 5)
{
if(ping_hdr->i_code == 0)
fprintf(stdout, "對(duì)網(wǎng)絡(luò)重定向. ");
if(ping_hdr->i_code == 1)
fprintf(stdout, "對(duì)主機(jī)重定向. ");
}
}
}
Sleep(seconds);
}//end for
//計(jì)算ping統(tǒng)計(jì)信息
fprintf(stdout, " Ping %s 的統(tǒng)計(jì)信息: ",destIP);
fprintf(stdout, " 包: 發(fā)送 = %d, 收到 = %d, 丟失 = %d (丟失率: %.0f%%) ",
i, totalrecv, (i-totalrecv), ((float)(i-totalrecv))/i*100 );
if(totalrecv != 0)//沒收到包打印路由信息無意義
{
fprintf(stdout, "近似路由時(shí)間(毫秒): ");
fprintf(stdout, " 最大 = %dms, 最小 = %dms, 平均 = %dms ", maxtime, mintime, (maxtime+mintime)/2);
}
return 0;
}
int main(int argc, char* argv[])
{
DWORD lpvBuffer = 1;
DWORD lpcbBytesReturned = 0;
int nNetTimeout=3000;//超時(shí)3秒
//初始化套結(jié)字
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData) != 0)
{
printf("fail to init socket: %d",WSAGetLastError());
return -1;
}
//創(chuàng)建套結(jié)字
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int));
if(sock == SOCKET_ERROR)
{
printf("fail to create socket: %d",WSAGetLastError());
return -1;
}
//獲取本機(jī)IP
if(gethostname(name, MAX_HOSTNAME_LEN))
{
printf("get host name error: %d",WSAGetLastError());
return -1;
}
pHostent = (struct hostent *)malloc(sizeof(struct hostent));
pTmp = pHostent;
pHostent = gethostbyname(name);
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_port = htons(0);
memcpy(&LocalAddr.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);
//bind socket
if(bind(sock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR)
{
printf("bind error: %d",WSAGetLastError());
return -1;
}
/*
//置網(wǎng)卡為混雜模式
//在這個(gè)ping程序中,不能將網(wǎng)卡置于混雜模式,否則接收的報(bào)文包括自己發(fā)送的報(bào)文 (^_^)
if(WSAIoctl(sock, SIO_RECALL, &lpvBuffer ,sizeof(lpvBuffer), NULL, 0,
&lpcbBytesReturned, NULL, NULL) == SOCKET_ERROR)
{
printf("WSAIoctl(

return -1;
}
*/
//命令行解析
if(argc < 2)
{
printf("必須輸入ping參數(shù)! ");
help();
return -1;
}
else
{
for(int i=1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch( (tolower(argv[i][1])) )
{
case 'a':
hostToIp = true;
break;
case 't':
pingforever = true;
break;
case 'h':
help();
return -1;
break;
case 'q'://ping只在開始和結(jié)束時(shí)打印一些概要信息
isSimple = true;
break;
case 'c':
{
if( *(argv[i]+3) > '9' || *(argv[i]+3) < '0' )
{
printf("ping次數(shù)錯(cuò)誤參數(shù)! ");
help();
return -1;
}
//發(fā)送報(bào)文次數(shù)
total = atoi(argv[++i]);
break;
}
case 'i'://設(shè)置發(fā)送報(bào)文時(shí)間差
{
if( *(argv[i]+3) > '9' || *(argv[i]+3) < '0' )
{
printf("時(shí)間錯(cuò)誤參數(shù)! ");
help();
return -1;
}
//發(fā)送報(bào)文次數(shù)
seconds = atoi(argv[++i]) * 1000;
break;
}
default:
break;
}//end switch
}//end if
}//end for
if( (argv[argc-1][0]) > '9' || (argv[argc-1][0]) < '0' )
{
printf("目的IP錯(cuò)誤!請(qǐng)確認(rèn)最后一個(gè)參數(shù)是目的IP. ");
help();
return -1;
}
memcpy(destIP, argv[argc-1], strlen(argv[argc-1]));
}
//發(fā)送ping報(bào)文
funPing();
free(pTmp);
closesocket(sock);
WSACleanup();
return 0;
}