简易ping程序

原创 2012年03月31日 08:40:23

当我把icmp的检验和设置成0时,ping百度是可以有echo返回。但是ping其他主机是没有返回响应。

手动添加检验和后正常。

原因:可能是baidu服务器并没有检测校验和就返回一个echo,这样可以减少服务器的负担。

而其他一些站点都会校验。


注意点:IPV4的icmp,在原始套接字收到后,收到的是包含IP头在内的完整数据报

IPV6的icmp,则是去除所有ip头和扩展头部的净载荷。

#include "unp.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <assert.h>
char 	sendbuf[MAXLINE], recvbuf[MAXLINE];
int 		datalen = 56,	 nseq = 0;
int 		sockfd;
struct sockaddr_in	dst, src;
socklen_t 		dstlen, srclen;


void callfunc(int signo) ;
void send_icmp( ) ;
void  recv_icmp();
unsigned short icmp_cksum(unsigned short *addr, int len);

int	main( int argc, char **argv) {
	if(argc  != 2) {
		err_quit("args");
	}
	char buf[100];
	struct addrinfo *addr, hints, *next;
	struct sockaddr *servaddr;
	struct sockaddr_in *temp;
	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	getaddrinfo(argv[1], NULL, &hints, &addr);
	for(; addr != NULL; addr = addr->ai_next) {
		temp = (struct sockaddr_in *)(addr->ai_addr);
		dst = *temp;
		dstlen = srclen = sizeof(struct sockaddr);
		 printf("the dst ip is %s\n", inet_ntop(AF_INET, &(temp->sin_addr), buf, sizeof(buf)));
		break;
	}
	sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	setuid(getuid());
	signal(SIGALRM, callfunc);
	callfunc(SIGALRM);
	for(;;) {
		recv_icmp();
	}
}
void callfunc(int signo) {
	send_icmp();
	alarm(1);
}
void send_icmp( ) {
	struct icmp		*icmp;
	/*		struct timeval		*timeval;*/
	icmp = (struct icmp *)sendbuf;
	icmp->icmp_type = 8;
	icmp->icmp_code = 0;
	icmp->icmp_cksum = 0;
	icmp->icmp_id = 88;
	icmp->icmp_seq = nseq ++;
	gettimeofday((struct timeval *)(icmp->icmp_data), NULL);
	icmp->icmp_cksum = icmp_cksum((u_short *)icmp, 56+8);
	sendto(sockfd, sendbuf, 56+8, 0, (SA *)&dst, dstlen);
	return;
}
void cal_time(struct timeval *time1, struct timeval *time2) { /*大 小*/
	time1->tv_usec = ((time1->tv_usec)/1000) + ((time1->tv_sec)*1000);
	time2->tv_usec = ((time2->tv_usec)/1000) + ((time2->tv_sec)*1000);
	time1->tv_usec = (time1->tv_usec) -(time2->tv_usec);
}
void  recv_icmp() {
	struct ip		*ip;
	struct icmp	*icmp;
	struct timeval *rtime;
	int			n,hl;
	char 	buf[100];
	again:
	if(( n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (SA *)&src, &srclen) ) < 0) {
		if(errno == EINTR)
			goto again;
		else
			exit(0);
	}
	//printf("return a echo\n");

	ip = (struct ip *)recvbuf;
	hl = ip->ip_hl;
	hl = hl<< 2;
	icmp = (struct icmp *)(recvbuf + hl);
	if(icmp == NULL)
		printf("icmp is null\n");
	assert(icmp);
	assert(recvbuf);
	rtime = (struct timeval *)malloc(sizeof(struct timeval));
	if((icmp->icmp_type == 0) && (icmp->icmp_code == 0) &&(icmp->icmp_id == 88)){
		gettimeofday(rtime, NULL);
		cal_time(rtime, (struct timeval *)(icmp->icmp_data));
		printf("The seq %d ,", icmp->icmp_seq);
		printf("Ping the ip is %s :", inet_ntop(AF_INET,&( (&src)->sin_addr), buf, sizeof(buf)));
		printf("ttl  %d  ms\n", rtime->tv_usec);
		
	}
}

unsigned short icmp_cksum(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);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

利用c实现简易的ping

测延时也可以发送ICMP报文,通过SOCKET创建ICMP的socket。代码也一并贴出。#include #include #include #include #include #incl...

Socket编程之ping程序的实现

ping程序的实现,网络协议分析,TCP/IP协议详解的课程设计,Socket网络编程

linux上Ping程序的实现

在学习了TCP/IP详解之后,对于Ping程序的理解比较s

“ping”程序知多少

最近阅读了《TCP/IP详解 卷1:协议》。作者对“TCP/IP协议族”进行了详细的介绍,让读者对因特网上运行的协议有了一个全面的了解。本书共三十章,协议的总数也很多,不失为一本很好的网络参考书。 ...

解决网络ping内外网成功,但浏览器等应用程序连不上网(视个人情况而定)

很不幸第一次碰到这种事情,

用C语言实现Ping程序功能

简介: 大部分人用ping命令只是作为查看另一个系统的网络连接是否正常的一种简单方法。在这篇文章中,作者将介绍如何用C语言编写一个模拟ping命令功能的程序。ping命令是用来查看网络上另一个主机系统...

ping源码代阅读(三)UDP数据报程序

非连接的通信是一种什么情况呢? 可以通过sedto向任何一个套接口发送数据,如果想收听某一套接口上别人发送过来的数据,通过bind绑定到这个套接中,使用recvfrom接收. 如果想做应答,那么通...

UDP协议和Ping程序

UDP是一个简单的面向数据报的不可靠的无连接的运输层协议。UDP报文格式: 源端口号:16位。 目标端口号:16位。 数据报长度:16位。包含首部和数据。 检验和:16位。检验覆盖首部和数据部...

《UNIX网络编程 卷1》 笔记: 原始套接字—ping程序

原始套接字提供普通的TCP和UDP套接字所不提供的以下3个能力:     1. 进程可以读写ICMPv4、IGMPv4、ICMPv6分组。     2. 进程可以读写内核不处理其协议字段的IPv4数据...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)