`
mixer_a
  • 浏览: 344238 次
社区版块
存档分类
最新评论

ping 命令工作原理详细解析

 
阅读更多
ping的原理就是首先建立通道,然后发送包,对方接受后返回信息,这个包至少包括以下内容,发送的时候,包的内容包括对方的ip地址和自己的地址,还有序列数,回送的时候包括双方地址,还有时间等,主要是接受方在都是在操作系统内核里做好的,时刻在监听,提供一段c程序的代码,希望对大家有用。

<script id="ad_text_pcjob" src="http://www.pconline.com.cn/script/ad_text_pcjob.js" defer></script>#include <stdio.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <setjmp.h>
#include <errno.h>

#define PACKET_SIZE 4096
#define MAX_WAIT_TIME 5
#define MAX_NO_PACKETS 3

char sendpacket[PACKET_SIZE];
char recvpacket[PACKET_SIZE];
int sockfd,datalen=56;
int nsend=0,nreceived=0;
struct sockaddr_in dest_addr;
pid_t pid;
struct sockaddr_in from;
struct timeval tvrecv;

void statistics(int signo);
unsigned short cal_chksum(unsigned short *addr,int len);
int pack(int pack_no);
void send_packet(void);
void recv_packet(void);
int unpack(char *buf,int len);
void tv_sub(struct timeval *out,struct timeval *in);

void statistics(int signo)
{ printf("/n--------------------PING statistics-------------------/n");
printf("%d packets transmitted, %d received , %%%d lost/n",nsend,nreceived,
(nsend-nreceived)/nsend*100);
close(sockfd);
exit(1);
}
/*校验和算法*/
unsigned short cal_chksum(unsigned short *addr,int len)
{ int nleft=len;
int sum=0;
unsigned short *w=addr;
unsigned short answer=0;

/*把ICMP报头二进制数据以2字节为单位累加起来*/
while(nleft>1)
{ sum+=*w++;
nleft-=2;
}
/*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/
if( nleft==1)
{ *(unsigned char *)(&answer)=*(unsigned char *)w;
sum+=answer;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer=~sum;
return answer;
}
/*设置ICMP报头*/
int pack(int pack_no)
{ int i,packsize;
struct icmp *icmp;
struct timeval *tval;

icmp=(struct icmp*)sendpacket;
icmp->icmp_type=ICMP_ECHO;
icmp->icmp_code=0;
icmp->icmp_cksum=0;
icmp->icmp_seq=pack_no;
icmp->icmp_id=pid;
packsize=8+datalen;
tval= (struct timeval *)icmp->icmp_data;
gettimeofday(tval,NULL); /*记录发送时间*/
icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/
return packsize;
}
/*发送三个ICMP报文*/
void send_packet()
{ int packetsize;
while( nsend<MAX_NO_PACKETS)
{ nsend++;
packetsize=pack(nsend); /*设置ICMP报头*/
if( sendto(sockfd,sendpacket,packetsize,0,
(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0 )
{ perror("sendto error");
continue;
}
sleep(1); /*每隔一秒发送一个ICMP报文*/
}
}

/*接收所有ICMP报文*/
void recv_packet()
{ int n,fromlen;
extern int errno;

signal(SIGALRM,statistics);
fromlen=sizeof(from);
while( nreceived<nsend)
{ alarm(MAX_WAIT_TIME);
if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
(struct sockaddr *)&from,&fromlen)) <0)
{ if(errno==EINTR)continue;
perror("recvfrom error");
continue;
}
gettimeofday(&tvrecv,NULL); /*记录接收时间*/
if(unpack(recvpacket,n)==-1)continue;
nreceived++;
}

}
/*剥去ICMP报头*/
int unpack(char *buf,int len)
{ int i,iphdrlen;
struct ip *ip;
struct icmp *icmp;
struct timeval *tvsend;
double rtt;

ip=(struct ip *)buf;
iphdrlen=ip->ip_hl<<2; /*求ip报头长度,即ip报头的长度标志乘4*/
icmp=(struct icmp *)(buf+iphdrlen); /*越过ip报头,指向ICMP报头*/
len-=iphdrlen; /*ICMP报头及ICMP数据报的总长度*/
if( len<8) /*小于ICMP报头长度则不合理*/
{ printf("ICMP packets/'s length is less than 8/n");
return -1;
}
/*确保所接收的是我所发的的ICMP的回应*/
if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) )
{ tvsend=(struct timeval *)icmp->icmp_data;
tv_sub(&tvrecv,tvsend); /*接收和发送的时间差*/
rtt=tvrecv.tv_sec*1000+tvrecv.tv_usec/1000; /*以毫秒为单位计算rtt*/
/*显示相关信息*/
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;
}

main(int argc,char *argv[])
{ struct hostent *host;
struct protoent *protocol;
unsigned long inaddr=0l;
int waittime=MAX_WAIT_TIME;
int size=50*1024;

if(argc<2)
{ printf("usage:%s hostname/IP address/n",argv[0]);
exit(1);
}

if( (protocol=getprotobyname("icmp") )==NULL)
{ perror("getprotobyname");
exit(1);
}
/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/

if( (sockfd=socket(AF_INET,SOCK_RAW,protocol->p_proto) )<0)
{ perror("socket error");
exit(1);
}
/* 回收root权限,设置当前用户权限*/
setuid(getuid());
/*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size) );
bzero(&dest_addr,sizeof(dest_addr));
dest_addr.sin_family=AF_INET;

/*判断是主机名还是ip地址*/
if( inaddr=inet_addr(argv[1])==INADDR_NONE)
{ if((host=gethostbyname(argv[1]) )==NULL) /*是主机名*/
{ perror("gethostbyname error");
exit(1);
}
memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);
}
else /*是ip地址*/
memcpy( (char *)&dest_addr,(char *)&inaddr,host->h_length);
/*获取main的进程id,用于设置ICMP的标志符*/
pid=getpid();
printf("PING %s(%s): %d bytes data in ICMP packets./n",argv[1],
inet_ntoa(dest_addr.sin_addr),datalen);
send_packet(); /*发送所有ICMP报文*/
recv_packet(); /*接收所有ICMP报文*/
statistics(SIGALRM); /*进行统计*/

return 0;

}
/*两个timeval结构相减*/
void tv_sub(struct timeval *out,struct timeval *in)
{ if( (out-&gt;tv_usec-=in->tv_usec)<0)
{ --out->tv_sec;
out->tv_usec+=1000000;
}
out->tv_sec-=in->tv_sec;
}
/*------------- The End -----------*/

分享到:
评论

相关推荐

    ping 命令工作原理详细解析.rar_ping_ping 命令

    ping 命令工作原理详细解析

    tnsping命令解析

    本文详述了tnsping命令的原理及该命令的使用

    IP新技术进阶系列 - SRv6 Ping&Tracert深度解析

    本次课程将选取对SRv6网络进行Ping&Tracert检测的场景,以一个示例为主线,深度解析检测过程,解密报文交互与协议扩展,通过介绍关键命令的使用场景,展示详细的配置与验证过程,最后对该场景的检测原理做一个总结。...

    ping命令,抓包文件,可用wireshark等抓包工具解析

    ping命令,抓包文件,可用wireshark等抓包工具解析,帮助学习理解网络编程原理,由此可延伸到tcp http等协议的抓包分析

    计算机网络课程设计ping程序

    通过原始套接字编程,模拟Ping命令,实现其基本功能,即输入一个IP地址或一段IP地址的范围,分别测试其中每个IP地址所对应主机的可达性,并返回耗时、生存时间等参数,并统计成功发送和回送的Ping报文。 初始化...

    (视频)IP新技术进阶系列 - SRv6 Ping&Tracert深度解析

    本次课程将选取对SRv6网络进行Ping&Tracert检测的场景,以一个示例为主线,深度解析检测过程,解密报文交互与协议扩展,通过介绍关键命令的使用场景,展示详细的配置与验证过程,最后对该场景的检测原理做一个总结。...

    计算机网络技术实验2-ping实战

    2.掌握利用 ping 命令测试和分析主机的网络配置、网络连通性、网络延迟和域名解析的方法,具备基本的检错和排错能力。 实验装置 一台连入本地局域网或互联网的 Microsoft Windows 10 主机。 实验原理 ping 是最...

    必须掌握的八个DOS命令(全解析)

    一,ping  它是用来检查网络是否通畅或者网络连接速度的命令。作为一个生活在网络上的管理员或者黑客来说,ping命令是第一个必须掌握的DOS命令,它所利用的原理是这样的:

    Ping程序设计(c语言毕业课程设计).doc

    本章着 重讲述ping命令的实现原理和c语言的网络编程方法。读者可以在本章的基础上,对本章 实现的ping命令进行扩展,开发出功能更强大、更完善的ping命令,并进一步掌握网络 编程的方法。 9.1 设计目的 本章通过设计...

    计算机网络原理期末课程设计

    任务一 (1) 写出常用网络命令ipconfig, ping, netstat, ...要求有详细的说明文档,包括程序的设计思想、工作流程、关键问题、程序注释和对捕获包的解析截图。 编程语言不作要求,可使用自己熟悉的C、C++、java或C#等。

    入门学习Linux常用必会60个命令实例详解doc/txt

    ◆ 网络操作命令:ifconfig、ip、ping、netstat、telnet、ftp、route、rlogin、rcp、finger、mail、 nslookup; ◆ 系统安全相关命令:passwd、su、umask、chgrp、chmod、chown、chattr、sudo ps、who; ◆ 其它...

    以太网芯片CH395资料-支持国产.rar

    | | |---EXAM8: C示例源程序,CH395 DNS域名解析应用实例,根据域名解析对应IP | | |---EXAM9: C示例源程序,CH395 MAIL应用实例,演示使用CH395进行邮件收发 | | |---EXAM10: C示例源程序,CH395 FTP服务器应用...

    企业级Linux服务攻略

    1.3.1 ping命令检测网络状况 1.3.2 netstat命令 1.3.3 nslookup测试域名解析 1.4 本章习题 第2章 Samba服务 2.1 Samba原理 2.1.1 Samba概述 2.1.2 Samba应用环境 2.1.3 Samba工作原理 2.2 安装Samba服务 2.2.1 ...

    《新手学黑客攻防》┊神龙工作室[.PDF]

    1.5.1 ping命令 18 1.5.2 netstat命令 19 1.5.3 net命令 21 1. net localgroup 21 2. net user 23 1.5.4 dos基本命令 24 1. dir命令 24 2. cd命令 25 3. md和rd命令 26 4. del命令 27 5. copy命令 27 新手问题解答 ...

    网络安全实验---NMAP扫描.docx

    了解信息搜集的一般步骤 学会熟练使用ping命令 学会利用Nmap等工具进行信息搜集 实验内容和原理 1.信息搜集的步骤 攻击者搜集目标信息一般采用七个基本的步骤: (1) 找到初始信息,比如一个IP地址或者一个域名;...

    HP-UX系统管理(高级)

    14.5.4 ping命令152 14.5.5 netstat -i命令.153 14.5.6 netstat -r命令.154 14.5.7 nslookup命令.156 14.6 启动或禁止网络服务156 14.6.1 internet服务的服务进程启动.156 14.6.2 配置/etc/services文件.157 14.6.3 ...

    计算机网络实验实验报告1.doc

    " " " " "实验过程描 "网络常用命令的使用 " "述 "掌握PING命令的基本使用方法(包括参数的使用),对网络" " "常见故障利用命令进行分析判断 " " "用Tracert命令用来显示数据包到达目标主机所经过的路径 " " ",并...

    计算机网络实验实验报告.doc

    " " " " "实验过程描 "网络常用命令的使用 " "述 "掌握PING命令的基本使用方法(包括参数的使用),对网络" " "常见故障利用命令进行分析判断 " " "用Tracert命令用来显示数据包到达目标主机所经过的路径 " " ",并...

    dns服务器是什么.txt

    完成后在客户端的命令提示符下再次执行Ping命令,域名解析出的IP地址仍是修改前的地址"10.202.100.2",仍然会Ping不通。 巧用命令清除缓存 我们可在命令提示符下使用命令来清除DNS客户端缓存中的信息。在客户端执行...

    Ubuntu权威指南(2/2)

    9.2.4 显示进程的详细状态 信息 253 9.2.5 显示进程间的调用关系 253 9.2.6 pstree命令 254 9.3 监控进程及系统资源 255 9.4 终止进程的运行 259 9.5 调整分时进程的优先级 261 9.5.1 nice命令 261 9.5.2 renice命令...

Global site tag (gtag.js) - Google Analytics