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

📄 ping.cpp

📁 这是一个在Linux下实现的ping程序
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/ip_icmp.h>

#define WAIT_TIME 3
#define BUFFER_SIZE 1024

//ICMP报头解析代码
int unpack_packet_header(char * buf,int len,struct sockaddr_in *from)
{
	int i,iphdrlen;
	struct ip*ip;
	struct icmp* icmp;
	struct timeval *tvsend;
	struct timeval tvrecv;
	double rtt;

	ip=(struct ip*)buf;
	iphdrlen=ip->ip_hl*4;
	icmp=(struct icmp *)(buf+iphdrlen);
	len-=iphdrlen;
	if(len<8)
	{
		printf("ICMP packets\' s length is less than 8\n");
		return -1;
	}
	if(icmp->icmp_type==ICMP_ECHOREPLY)
	{
		tvsend=(struct timeval *)icmp->icmp_data;
		gettimeofday(&tvrecv,NULL);
		if((tvrecv.tv_usec-=tvsend->tv_usec)<0)
		{
			tvrecv.tv_sec--;
			tvrecv.tv_usec+=1000000;
		}
		tvrecv.tv_sec-=tvsend->tv_sec;
		rtt=tvrecv.tv_sec *1000+tvrecv.tv_usec/1000;
		printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f ms\n",
			   len,
			   inet_ntoa(from->sin_addr),
			   icmp->icmp_seq,
			   ip->ip_ttl,
		       rtt);
	}
	else
		return -1;
}

u_short cal_cksum(const u_short *addr,register int len, u_short csum)
{
	register int nleft=len;
	const u_short *w=addr;
	register u_short answer;
	register int sum=csum;

	while(nleft>1)
	{
		sum+=*w++;
		nleft-=2;
	}
	if(nleft==1)
	sum+=htons(*(u_char *)w<<8);

	sum=(sum>>16)+(sum & 0xffff);
	sum+=(sum>>16);
	answer=~sum;
	return (answer);
}
int main(int argc,char *argv[])
{
	int sock;
	struct sockaddr_in sin;
	unsigned short local_port;
	unsigned char protocol;
	char * buffer,*buffer2,*dnsdata;
	struct iphdr *ip_header;
	struct icmphdr *icmp_header;
	char *remote_ip_str;
	unsigned short buffer_size,buffer_size2;
	int tmp,len;
	short randomseq;

	if(argc!=3)
	{
		printf("two arguments \n");
		return 0;
	}
    protocol=IPPROTO_ICMP;
	local_port=atoi(argv[1]);
	remote_ip_str=argv[2];

	sock=socket(PF_INET,SOCK_RAW,protocol);
	if(sock<0)
	{
		printf("create socket error\n");
		return 0;
	}
	memset(&sin,0,sizeof(sin));
	sin.sin_port=htons(local_port);
	if(bind(sock,(struct sockaddr *)&sin,sizeof(sin))<0)
	{
		printf("bind error\n");
		return 0;
	}
	tmp=1;
	setsockopt(sock,0,IP_HDRINCL,&tmp,sizeof(tmp));

	buffer_size=sizeof(struct iphdr)+sizeof(struct icmphdr)+sizeof(struct timeval);

	buffer_size2=BUFFER_SIZE;
	memset(buffer,0,sizeof(buffer));
	
	memset(&sin,0,sizeof(sin));
    sin.sin_family=AF_INET;
	sin.sin_addr.s_addr=inet_addr(remote_ip_str);

	ip_header=(struct iphdr *)buffer;
	ip_header->ihl=5;
	ip_header->version=4;
	ip_header->tos=0;
	ip_header->tot_len=htons(buffer_size);
	ip_header->id=rand();
	ip_header->ttl=64;
	ip_header->frag_off=0x40;
	ip_header->protocol=protocol;
	ip_header->check=0;
	ip_header->daddr=inet_addr(remote_ip_str);
	ip_header->saddr=0;

	icmp_header=(struct icmphdr *)(ip_header+1);
	icmp_header->type=ICMP_ECHO;
	icmp_header->code=0;
	icmp_header->un.echo.id=htons(local_port);
	icmp_header->un.echo.sequence=0;

	struct timeval *tp=(struct timeval *)&buffer[28];
	gettimeofday(tp,NULL);

   icmp_header->checksum=cal_cksum((const u_short *) icmp_header,sizeof(struct icmphdr)
	   +sizeof(struct timeval),0);
   if(sendto(sock,buffer,buffer_size,0,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))  <0)
   {
	   printf("send error\n");
	   return 0;
   }
   printf("send ICMP inquery\n");
   len=sizeof(sin);
   
   //不同之处//////////////////////////////////
   alarm(WAIT_TIME);



   ////////////////////////////////////////
   if(recvfrom(sock,buffer2,buffer_size2,0,(struct sockaddr *)&sin,&len)<0)
   {
	   printf("receive error\n");
	   return 0;
   }
   printf("received Destionation response\n");
   
   //显示报文信息
   unpack_packet_header(buffer2,buffer_size2,(struct sockaddr_in *)&sin);

   close(sock);
   return 0;

}




⌨️ 快捷键说明

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