⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myping.cpp

📁 用C实现的Ping程序
💻 CPP
字号:
//author: 10203201 张锟

#include<stdio.h>
#include<windows.h>
#include<process.h>

#pragma comment(lib,"ws2_32.lib")


#define SEND_SIZE 32 
#define PACKET_SIZE 4096

//echo
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0

//timestamp request
#define ICMP_TSTAMP 13
#define ICMP_TSTAMPREPLY 14

//mask request
#define ICMP_MASKREQ 17
#define ICMP_MASKREPLY 18

struct icmp
{
	unsigned char icmp_type;
	unsigned char icmp_code;
	unsigned short icmp_cksum;
	unsigned short icmp_id;
	unsigned short icmp_seq;

	union
	{
		struct timestamp
		{
			unsigned long or_time;
			unsigned long re_time;
			unsigned long tr_time;
		} t_stamp;
		
		unsigned long submask;

		unsigned long data;
	} icmp_option;
};

struct ip
{ 
    unsigned char ip_hl:4;        
	unsigned char ip_v:4;      
    unsigned char ip_tos;           
    unsigned short ip_len;         
    unsigned short ip_id;          
    unsigned short ip_off;         
    unsigned char ip_ttl;           
    unsigned char ip_p;          
    unsigned short ip_sum;         
    unsigned long ip_src;
    unsigned long ip_dst;  
};

unsigned char sendpacket[PACKET_SIZE];
unsigned char recvpacket[PACKET_SIZE];
struct sockaddr_in dest_addr;
struct sockaddr_in sour_addr;
int sockfd;
int pid;
int icmp_type;
unsigned long icmp_sendtime;

unsigned short cal_chksum(unsigned short *addr,int len);
int pack(int pack_no);
int unpack(unsigned char *buf,int len);
void send_packet(void);
void recv_packet(void);

void main(int argc,char *argv[])
{       
	hostent *host;
	WSADATA wsaData;
	int timeout = 1000;
	int SEND_COUNT = 4;
	int i;
	char *des_host;

	des_host = argv[argc-1];
	icmp_type = ICMP_ECHO;

	switch(argc)
	{
	case 2:
		break;
	case 3: 
		if(strcmp(argv[1],"-t") == 0)
		{
			SEND_COUNT=10000;
			break;
		}
		else if(strcmp(argv[1],"-m") == 0)
		{
			icmp_type = ICMP_MASKREQ;
			break;
		}
		else if(strcmp(argv[1],"-s") == 0)
		{
			icmp_type = ICMP_TSTAMP;
			break;
		}
	default:
		printf("usage: %s [-t] [-m] [-s] Host name or IP address\n",argv[0]);
		printf("	-t: ping until stopped\n	-m: request for subnet mask\n	-s: request for timestamp\n"); 
		exit(1); 
	}

	if(WSAStartup(0x1010,&wsaData)!=0)
	{
		printf("wsastartup error\n");
		exit(1);
	}

	if((sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0)
	{   
		printf("socket error\n");
		exit(1);
	}
	if(setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout))<0)  
		fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());
	if(setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout))<0)
		fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());        

	memset(&dest_addr,0,sizeof(dest_addr));
	dest_addr.sin_family = AF_INET; 

	if(host = gethostbyname(des_host))
	{
		memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);
		if(host = gethostbyaddr(host->h_addr,4,PF_INET))
			des_host = host->h_name;
	}

	else if((dest_addr.sin_addr.s_addr = inet_addr(des_host)) == INADDR_NONE)
	{
		printf("Unkown host %s\n",des_host);
		exit(1);
	}

	      
	pid = getpid();

	printf("Pinging %s [%s]: with %d bytes of data:\n\n",des_host,inet_ntoa(dest_addr.sin_addr),SEND_SIZE);

	for(i=0;i<SEND_COUNT;i++)                        
	{
		send_packet();
		recv_packet();
		if(i != SEND_COUNT-1)
			Sleep(1000);
	}
}

//this algorithm is referenced from other's 
unsigned short cal_chksum(unsigned short *addr,int len)
{       
	int nleft=len;
	int sum=0;
	unsigned short *w=addr;
	unsigned short answer=0;
	 
	while(nleft>1)
	{       
		sum+=*w++;
		nleft-=2;
	}
	if( nleft==1)
	{       
		*(unsigned char *)(&answer)=*(unsigned char *)w;
		sum+=answer;
	}
	
	sum=(sum>>16)+(sum&0xffff);
	sum+=(sum>>16);
	answer=~sum;
	return answer;
}

//pack
int pack(int pack_no)
{       
	int packsize;
	struct icmp *icmp;

	switch(icmp_type)
	{
	case ICMP_ECHO:
		packsize = 8 + SEND_SIZE;
		break;
	case ICMP_TSTAMP:
		packsize = 20;
		break;
	case ICMP_MASKREQ:
		packsize = 12;
		break;
	default:
		break;
	}

	icmp = (struct icmp*)sendpacket;
	icmp->icmp_type = icmp_type;
	icmp->icmp_code = 0;
	icmp->icmp_cksum = 0;
	icmp->icmp_seq = pack_no;
	icmp->icmp_id = pid;
	if(icmp_type == ICMP_TSTAMP)
	{
		icmp->icmp_option.t_stamp.or_time = GetTickCount();
		icmp->icmp_option.t_stamp.re_time = 0;
		icmp->icmp_option.t_stamp.tr_time = 0;
	}
	else if(icmp_type == ICMP_MASKREQ)
		icmp->icmp_option.submask = 0;
	else if(icmp_type == ICMP_ECHO)
		memcpy(&icmp->icmp_option.data,"宁静致远淡泊明志——湖北襄樊张锟",sizeof("宁静致远淡泊明志——湖北襄樊张锟"));

	icmp_sendtime = (unsigned long)GetTickCount();

	icmp->icmp_cksum = cal_chksum((unsigned short *)icmp,packsize); /*check sum*/

	return packsize;
}

//unpack
int unpack(unsigned char *buf,int len)
{ 
	struct ip *ip;
	struct icmp *icmp;
	double rtt;
	int iphdrlen;
	int icmphdrlen;
     
	ip = (struct ip *)buf;
	iphdrlen = ip->ip_hl * 4; 

	switch(icmp_type)
	{
	case ICMP_ECHOREPLY:
		icmphdrlen = 8;
	case ICMP_TSTAMPREPLY:
		icmphdrlen = 20;
	case ICMP_MASKREPLY:
		icmphdrlen = 12;
	}

	icmp = (struct icmp *)(buf + iphdrlen);
	if(icmp->icmp_id == pid)
	{
		len = len - 20 - 8; 
		rtt = GetTickCount() - icmp_sendtime;
		printf("Reply from %s: bytes=%d time=%.0fms TTL=%d icmp_seq=%u\n",inet_ntoa(sour_addr.sin_addr),len,rtt,ip->ip_ttl,icmp->icmp_seq);
		switch(icmp->icmp_type)
		{
		case ICMP_ECHOREPLY:
            break;			
		case ICMP_MASKREPLY:
			printf("\tsubnet mask:%s\n",icmp->icmp_option.submask);
			break;
		case ICMP_TSTAMPREPLY:
			printf("\toriginate timestamp: \t%d ms\n\treceive   timestamp: \t%d ms\n\ttransmit  timestamp: \t%d ms\n",icmp->icmp_option.t_stamp.or_time,icmp->icmp_option.t_stamp.re_time,icmp->icmp_option.t_stamp.tr_time);
			break;
		default:
			break;
		}

		return 1;
	}
	return 0;
}

//send
void send_packet()
{   
	int packetsize;
	static int pack_no=0;
    
	packetsize = pack(pack_no++); 
	if(sendto(sockfd,(char *)sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0)
		printf("Destination host unreachable.\n");
}


//receive
void recv_packet()
{    
	int n,fromlen;
	int success;

	fromlen = sizeof(sour_addr);

	do
	{
		if((n = recvfrom(sockfd,(char *)recvpacket,64,0,(struct sockaddr *)&sour_addr,&fromlen)) >= 0)
			success = unpack(recvpacket,n);
		else if (WSAGetLastError() == WSAETIMEDOUT) 
		{
			printf("Request timed out.\n");
			return;
		}
	}while(!success);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -