ping函数实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>




int sockfd,sentp,recvp,seq;
struct sockaddr_in dst;
typedef struct Icmphead
{
	u_char type;
	u_char code;
	u_short checksum;
	u_short id;
	u_short seq;
}icmphead;
u_short chksum(u_short*,int);
void ping()
{
	char sendpacket[100];
	int  icmpsize=8;
	
	icmphead*icmp;
	icmp=(icmphead*)sendpacket;
	icmp->type=8;
	icmp->code=0;
	icmp->checksum=0;
	icmp->id=icmp->seq=seq;
	icmp->checksum=chksum((u_short*)icmp,icmpsize);
	int len=sizeof(dst);
	if((sendto(sockfd,sendpacket,icmpsize,0,(struct sockaddr*)&dst,len))<0)
	{
		printf("sendto error\n");
		exit(0);
	}
	sentp++;
	alarm(1);
}
void result()
{
	if(sentp)
	{
		printf("sent packet %d recvpacket %d\n",sentp,recvp);
	}
	else
	{
		printf("no packet send successful\n");
	}
	exit(0);
}

u_short chksum(u_short*icmpdata,int icmpsize)
{
	u_short sum=0;
	while(icmpsize>1)
	{
		sum=sum+*(icmpdata++);
		icmpsize-=2;
	}
	if(icmpsize)
	{
		sum=sum+*icmpdata;
	}
	while(sum>>16)
		sum=(sum>>16)+(sum&0xffff);
	return ~sum;
}

int main()
{
	char hostname[100];
	printf("input hostname:");scanf("%s",hostname);
	struct hostent*h;
	dst.sin_family=AF_INET;
	seq=sentp=recvp=0;
	if(h=gethostbyname(hostname))
	{
		bcopy(h->h_addr,&dst.sin_addr,h->h_length);
		strcpy(hostname,(char*)inet_ntoa(dst.sin_addr));
		printf("hostname ip is %s\n",hostname);
	}
	else
	{
		printf("wrong hostname\n");
		exit(0);
	}
	if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0)
	{
		printf("create socket fail\n");
		exit(0);
	}
	signal(SIGINT,result);
	signal(SIGALRM,ping);
	alarm(1);
	for(;;)
	{
		char buf[100];
		int len=sizeof(dst);
		int recvsize=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr*)&dst,&len);
		if(recvsize<=0)
		{
			printf("recvfrom faild\n");
		}
		else
		{
			char info[100];
			icmphead*icmp;
			char *p;
			p=(char*)buf;
			icmp=(icmphead*)(p+20);
			if(icmp->type!=0){printf("not the reply type,type is %d\n",icmp->type);continue;}
			if(icmp->seq!=seq||icmp->id!=seq){printf("not the right echo,now seq is %d, but icmp->seq is %d\n",seq,icmp->seq);continue;}
			sprintf(info,"icmp_seq:%d",icmp->seq);
			printf("reply from %s:%s\n",hostname,info);
			recvp++;
			seq++;
		}

	}
	return 0;
}

对应上面的ping有几个地方要注意的是:

1,如果没有把发过去的包的校验码算准确,那么将得不到回应(尼吗在这里卡了好久好久,最后用wireshark才看出来校验码错了,根本没有回应)

2,在套接字设置时候,注意protol字段选择IPPROTO_ICMP,这样就只接受icmp和发送icmp了。

3,学会alarm和signal(SIGALRM,xxx)的用法。

4,注意到接受到的包带有ip包头,计算时候要跳过。

暂时就这么多了。。。。。











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值