ping命令實現內幕

2021-05-10 12:23:28 字數 4975 閱讀 5088

在網路上有不少ping命令的實現,但是要麼連執行都不行,要麼就是表層的僥倖的能成功一些例子。今我自己寫了個ping命令程式,自習研究了一下,原來問題頗多。。。。。。 很多還得看底層協議**才能搞清楚它的來龍去脈。。。 先將除錯版ping命令程式**貼上:

/***********************ping程式,completed by ben****************************/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define bufsize 1024

#define max_pack_num

char sendbuf[bufsize];

char recvbuf[bufsize];

//int buflen=128;

int datalen=56;

unsigned short pid;

struct sockaddr *sasend;

struct sockaddr *sarecv;

struct sockaddr_in *dst;

char abuf[inet_addrstrlen];

int sckadlen;

static unsigned short nsend=0;

int sockfd;

int recvnum=0;

int totaltime=0;

struct timeval sendtime,endtime;

//static int sendnum=0;

unsigned short cksum(unsigned short *addr ,int len)

if( nleft==1)

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;

return answer;

}void sendpkg()

struct icmp *icmp;

icmp=(struct icmp *)sendbuf;

icmp->icmp_type=icmp_echo;

icmp->icmp_code=0;

icmp->icmp_seq=htons(nsend++);

//icmp->icmp_seq=htons(0);

//printf("seq is %d/n",icmp->icmp_seq);

//printf("icmp_type is %x/n",&icmp->icmp_type);

//printf("icmp_seq is %x/n",&icmp->icmp_seq);

//printf("icmp->icmp_id is %x/n",&icmp->icmp_id);

//printf("icmp len is %d/n",sizeof(struct icmp));

//printf("icmp_data is %x/n",&icmp->icmp_data);

//printf("pid is %d/n",pid);

//icmp->icmp_id=htons(pid);

icmp->icmp_id=htons(pid);

//printf("icmp->icmp_id is %x/n",icmp->icmp_id);

//printf("sendbuf byte 4 is %d/n",sendbuf[4]);

//int n;

memset(icmp->icmp_data,0xa5,datalen);

gettimeofday((struct timeval *)icmp->icmp_data,null);

struct timeval *temptival=(struct timeval *)icmp->icmp_data;

temptival->tv_sec=ntohl(temptival->tv_sec);

temptival->tv_usec=ntohl(temptival->tv_usec);

if(nsend==1) gettimeofday(&sendtime,null);

//if(flag==0)  

int len=8+datalen;

//printf("heheheheh/n");

icmp->icmp_cksum=htons(cksum((unsigned short *)icmp,len));

//icmp->icmp_cksum=cksum((unsigned short *)icmp,len);

//printf("sasend->sa_len is %d/n",sasend->sa_family);

//sleep(1);

unsigned char a=8;

//printf("a is %x/n",a);

//for(n=0;n<64;n++)

// if((n=sendto(sockfd,sendbuf,len,0,sasend,sckadlen))<0)

//printf("n is %d /n",n);

return;

}void sig_alrm(int signo)

void tv_sub(struct timeval *out,struct timeval *in)

out->tv_sec-=in->tv_sec;

}void catchint(int signo)

void recvpkg()

//printf("n is %d/n",n);

//printf("error when recv/n");

//exit(-1);

//gettimeofday(tval,null);

ip=(struct ip*)recvbuf;

iph_len=ip->ip_hl<<2;

//printf("hehe/n");

if(ip->ip_p!=ipproto_icmp)

return;

//printf("hododo/n");

icmp=(struct icmp*)(recvbuf+iph_len);

icmplen=n-iph_len;

if(icmplen<8) continue;

//printf("jkjk/n");

if(icmp->icmp_type==icmp_echoreply&&ntohs(icmp->icmp_id)==pid)

else

continue;

}free(sarecv); 

printf("out of circle /n");

return;

}int main(int argc,char **argv)

struct addrinfo hints,*res;

struct sockaddr_in *dst;

bzero(&hints,sizeof(struct addrinfo));

hints.ai_flags=ai_canonname;

hints.ai_family=af_unspec;//0

hints.ai_socktype=0;

host=argv[1];

signal(sigalrm,sig_alrm);

signal(sigint,catchint);

pid=getpid();

printf("hi,pid is %d/n",pid);

if(getaddrinfo(host,null,&hints,&res)!=0)

sasend=res->ai_addr;

sckadlen=res->ai_addrlen;

//printf("sckadlen is %d/n",sckadlen);

dst=(struct sockaddr_in *)res->ai_addr;//dst=(sockaddr_in *)&res->ai_addr;

//sasend=dst

h=inet_ntop(af_inet,&dst->sin_addr,abuf,inet_addrstrlen);

if(h==null)

printf("h is %s/n",h);

printf("ping %s(%s):%d data bytes/n",res->ai_canonname?res->ai_canonname:h,h,datalen);

//int protocol;

struct protoent *protocol;

if( (protocol=getprotobyname("icmp") )==null)

sockfd=socket(af_inet,sock_raw,protocol->p_proto); //ipproto_icmp

int buflen=bufsize;

//printf("come to here:/n");

setsockopt(af_inet,sol_socket,so_rcvbuf,&buflen,sizeof(buflen));

sig_alrm(sigalrm);

//sendpkg();

recvpkg();

return 1;

} 對方接受到icmp資料報在ip層還會做處理:

當乙個i c m p報文到達時,i p層通過i n e t s w [ 4 ]的p r _ i n p u t

函式,間接呼叫i c m p _ i n p u t函式。

icmp_input->in_cksum():這個函式會重新計算校驗和,如果校驗和不對,接受到的包含icmp報文ip包將就不會被傳送。

ping命令的實現

ping命令的實現 include include include include include include include include include include include include include include include define packet size 4...

golang 實現ping 命令

在專案中,我們需要知道哪些ip是可用ip,這時候想到了用icmp internet控制報文協議 於是就在網上查詢,後來找到了乙個開源庫 github.com sparrc go ping。這個庫簡單好用,能達到專案需求,也推薦大家使用。貼乙個示例吧.當然你得先 go get github.com s...

ping 命令 Ping命令

簡單介紹使用ping命令檢查網路連線是否可達以及分析網路發生故障的位置。其中,ping用於檢查網路連線及主機是否可達 ping命令主要用於檢查網路連線及主機是否可達。ping功能是基於icmp協議來實現的 源端向目的端傳送icmp請求 echo request 報文後,根據是否收到目的端的icmp應...