如何在linux下用c语言linux上编写c语言一个能够发送icmp报文的小程序

18:56 提问
liunx 中的 ping 程序C源代码
想深入学习一下ping程序,但现在找到的代码都不能用。。。。求大神帮在linux下用C写一个ping程序。。。
按赞数排序
百度一下就有很多的
void statistics(int signo)
printf("\n--------------------PING statistics-------------------\n");
printf("%d packets transmitted, %d received , %d%%
nsend,nreceived,(nsend-nreceived)/nsend*100);
close(sockfd);
/*校验和算法*/
unsigned short cal_chksum(unsigned short *addr,int len)
int nleft=
int sum=0;
unsigned short *w=
unsigned short answer=0;
/*把ICMP报头二进制数据以2字节为单位累加起来*/
while(nleft&1)
sum+=*w++;
/*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高
//字节,这个2字节数据的低字节为0,继续累加*/
if( nleft==1)
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum=(sum&&16)+(sum&0xffff);
sum+=(sum&&16);
/*设置ICMP报头*/
int pack(int pack_no)
struct icmp *
struct timeval *
icmp=(struct icmp*)
icmp-&icmp_type=ICMP_ECHO;
icmp-&icmp_code=0;
icmp-&icmp_cksum=0;
icmp-&icmp_seq=pack_
icmp-&icmp_id=
packsize=8+
tval= (struct timeval *)icmp-&icmp_
gettimeofday(tval,NULL);
/*记录发送时间*/
icmp-&icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/
/*发送三个ICMP报文*/
void send_packet()
while( nsend&MAX_NO_PACKETS) //发送MAX_NO_PACKETS个ICMP报文
packetsize=pack(nsend); /*设置ICMP报头*/
//sendpacket为要发送的内容,由pack()函数设定,dest_addr是目的地址,
if( sendto(sockfd,sendpacket,packetsize,0,
(struct sockaddr *)&dest_addr,sizeof(dest_addr) )&0
perror("sendto error");
sleep(1); /*每隔一秒发送一个ICMP报文*/
/*接收所有ICMP报文*/
void recv_packet()
signal(SIGALRM,statistics);
fromlen=sizeof(from);
while( nreceived&nsend)
//alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程
alarm(MAX_WAIT_TIME);
if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
(struct sockaddr *)&from,&fromlen)) &0)
if(errno==EINTR)
perror("recvfrom error");
gettimeofday(&tvrecv,NULL);
/*记录接收时间*/
if(unpack(recvpacket,n)==-1)
nreceived++;
/*剥去ICMP报头*/
int unpack(char *buf,int len)
struct ip *
struct icmp *
struct timeval *
ip=(struct ip *)
//求ip报头长度,即ip报头的长度标志乘4,头长度指明头中包含的4字节字的个数。可接受
//的最小值是5,最大值是15
iphdrlen=ip-&ip_hl&&2;
icmp=(struct icmp *)(buf+iphdrlen);
/*越过ip报头,指向ICMP报头*/
/*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_
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);
return -1;
int main(int argc,char *argv[])
struct hostent *
struct protoent *
unsigned long inaddr=0l;
int waittime=MAX_WAIT_TIME;
//#define MAX_WAIT_TIME
int size=50*1024;
if(argc&2)
printf("usage:%s hostname/IP address\n",argv[0]);
//getprotobyname("icmp")返回对应于给定协议名的包含名字和协议号的protoent结构指针。
if( (protocol=getprotobyname("icmp") )==NULL)
perror("getprotobyname");
/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
if( (sockfd=socket(AF_INET,SOCK_RAW,protocol-&p_proto) )&0)
perror("socket error");
/* 回收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");
memcpy( (char *)&dest_addr.sin_addr,host-&h_addr,host-&h_length);
/*是ip地址*/
dest_addr.sin_addr.s_addr = inet_addr(argv[1]);
/*获取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); /*进行统计*/
/*两个timeval结构相减*/
void tv_sub(struct timeval *out,struct timeval *in)
if( (out-&tv_usec-=in-&tv_usec)&0)
--out-&tv_
out-&tv_usec+=1000000;
out-&tv_sec-=in-&tv_
可以参看linux内核源代码,busybox里面就有ping命令的实现
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)帮忙用C语言编写一个小程序_百度知道
帮忙用C语言编写一个小程序
新手,自学了半天还是没弄懂C语言原理,能帮忙用C语言编写一个小程序吗
调用printf()函数在一行上输出您的名和姓,在调用一次printf()函数在两个单独的行上输出您的名和姓,然后调用一对printf()函数在一行上输出您的名和姓,输出结果如下(用a代替姓,...
我有更好的答案
我好久都没用过C语言了,这个是用C++编译的
采纳率:35%
#include&stdio.h&//引用标准输入输出库头文件,你可以认为是固定格式,不懂的话int main()//main主函数{printf(&a b\n&);printf(&a\n&);printf(''b\n&);printf(&a b\n&);return 0;//返回值0,也可认为固定格式}//是注释行编译的话,你可以自己下载一个VC6.0编译软件。
本回答被网友采纳
#include&stdio.h&int main() { printf(&a b\n&); printf(&a\nb\n&); printf(&a &); printf(&b&); return 0; }
楼上的答案有点不和题意啊,应该是这样的:#include&stdio.h&int main(){printf(&a b\n&);printf(&a\nb\n&);printf(&a &);printf(&b\n&);return 0;}具体注释见楼上....
其他1条回答
为您推荐:
其他类似问题
您可能关注的内容
小程序的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。#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
3char sendpacket[PACKET_SIZE];char recvpacket[PACKET_SIZE];int sockfd,datalen=56;int nsend=0,nreceived=0;struct sockaddr_in dest_pid_struct sockaddr_structvoid 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=
int sum=0;
unsigned short *w=
unsigned short answer=0;
/*把ICMP报头二进制数据以2字节为单位累加起来*/
while(nleft&1)
sum+=*w++;
/*若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加*/
if( nleft==1)
*(unsigned char *)(&answer)=*(unsigned char *)w;
sum=(sum&&16)+(sum&0xffff);
sum+=(sum&&16);
return}/*设置ICMP报头*/int pack(int pack_no){
struct icmp *
struct timeval *
icmp=(struct icmp*)
icmp-&icmp_type=ICMP_ECHO;
icmp-&icmp_code=0;
icmp-&icmp_cksum=0;
icmp-&icmp_seq=pack_
icmp-&icmp_id=
packsize=8+
tval= (struct timeval *)icmp-&icmp_
gettimeofday(tval,NULL);
/*记录发送时间*/
icmp-&icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); /*校验算法*/
return}/*发送三个ICMP报文*/void send_packet(){
while( nsend&MAX_NO_PACKETS)
packetsize=pack(nsend); /*设置ICMP报头*/
if( sendto(sockfd,sendpacket,packetsize,0,
(struct sockaddr *)&dest_addr,sizeof(dest_addr) )&0
perror("sendto error");
sleep(1); /*每隔一秒发送一个ICMP报文*/
}}/*接收所有ICMP报文*/void recv_packet(){
extern int
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");
gettimeofday(&tvrecv,NULL);
/*记录接收时间*/
if(unpack(recvpacket,n)==-1)continue;
nreceived++;
}}/*剥去ICMP报头*/int unpack(char *buf,int len){
struct ip *
struct icmp *
struct timeval *
ip=(struct ip *)
iphdrlen=ip-&ip_hl&&2;
/*求ip报头长度,即ip报头的长度标志乘4*/
icmp=(struct icmp *)(buf+iphdrlen);
/*越过ip报头,指向ICMP报头*/
/*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_
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",
inet_ntoa(from.sin_addr),
icmp-&icmp_seq,
ip-&ip_ttl,
return -1;}main(int argc,char *argv[]){
struct hostent *
struct protoent *
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]);
if( (protocol=getprotobyname("icmp") )==NULL)
perror("getprotobyname");
/*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
if( (sockfd=socket(AF_INET,SOCK_RAW,protocol-&p_proto) )&0)
perror("socket error");
/* 回收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");
memcpy( (char *)&dest_addr.sin_addr,host-&h_addr,host-&h_length);
/*是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-&tv_usec-=in-&tv_usec)&0)
--out-&tv_
out-&tv_usec+=1000000;
out-&tv_sec-=in-&tv_}/*------------- The End -----------*/
仍然需要注意权限的问题,按照如下方式编译:
sudo gcc myping.c -o myping
sudo chmod u+s myping
./myping www.163.com
运行显示结果:
PING www.cn.ibm.com(121.195.178.238): 56
bytes data in ICMP packets.
64 byte from 121.195.178.238: icmp_seq=1
ttl=242 rtt= ms
64 byte from 121.195.178.238: icmp_seq=2
ttl=242 rtt= ms
64 byte from 121.195.178.238: icmp_seq=3
ttl=242 rtt= ms
--------------------PING
statistics-------------------
3 packets transmitted, 3 received , %0 lost
阅读(...) 评论()C语言编写小程序_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C语言编写小程序
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩1页未读,
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 linux编写c语言程序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信