一个函数实现网络故障诊断

该代码由网上的文章“微软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; 
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值