日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

ping命令工作原理詳細解析

【ping命令工作原理詳細解析】 ping的原理就是首先建立通道,然后發(fā)送包,對方接受后返回信息,這個包至少包括以下內(nèi)容,發(fā)送的時候,包的內(nèi)容包括對方的ip地址和自己的地址,還有序列數(shù),回送的時候包括雙方地址,還有時間等,主要是接受方在都是在操作系統(tǒng)內(nèi)核里做好的,時刻在監(jiān)聽,提供一段c程序的代碼,希望對大家有用 。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#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 lostn",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報頭二進制數(shù)據(jù)以2字節(jié)為單位累加起來*/
while(nleft>1)
{ sum =*w;
nleft-=2;
}

/*若ICMP報頭為奇數(shù)個字節(jié),會剩下最后一字節(jié) 。把最后一個字節(jié)視為一個2字節(jié)數(shù)據(jù)的高字節(jié),這個2字節(jié)數(shù)據(jù)的低字節(jié)為0,繼續(xù)累加*/
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); /*記錄發(fā)送時間*/
icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校驗算法*/
return packsize;
}

/*發(fā)送三個ICMP報文*/
void send_packet()
{ int packetsize;
while( nsend{ 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); /*每隔一秒發(fā)送一個ICMP報文*/

}
}

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

signal(SIGALRM,statistics);
fromlen=sizeof(from);
while( nreceived{ 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;
}
}

/*剝?nèi)CMP報頭*/
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數(shù)據(jù)報的總長度*/
if( len<8) /*小于ICMP報頭長度則不合理*/
{ printf("ICMP packets"s length is less than 8n");

推薦閱讀