wolflion

ping的源代码

http://blog.chinaunix.net/u1/48325/showart.php?id=719303用C语言实现Ping程序功能
http://blog.chinaunix.net/u1/48325/showart_719319.html【Linux下Ping的实现代码】

以下为ping的伪代码
  1#define PACKET_SIZE 4096
  2#define MAX_WAIT_TIME 5
  3
  4char sendpacket[PACKET_SIZE];
  5char recvpacket[PACKET_SIZE];
  6int sockfd,datalen=56;
  7int nsend=0,nreceived=0;
  8struct sockaddr_in dest_addr;
  9pid_t pid;
 10struct sockaddr in from;
 11struct timeval tvrecv;
 12
 13void statistics()
 14{
 15    printf(.);//打印统计信息
 16    close(sockfd);
 17    exit(1);
 18}

 19
 20//校验和算法
 21unsigned short cal chksum(unsigned short *addr,int len)
 22{
 23    .
 24}

 25
 26//设置ICMP报头
 27int pack(int pack_no)
 28{
 29    int i,packsize;
 30    struct icmp *icmp;
 31    struct timeval *tval;
 32
 33    icmp = (struct icmp*)sendpacket;
 34    icmp->icmp_type = ICMP_ECHO;
 35    icmp->icmp_code = 0;
 36    icmp->icmp_cksum = 0;
 37    icmp->icmp_seq = pack_no;
 38    icmp->icmp_id = pid;
 39
 40    packsize = 8+datalen;
 41    tval = (struct timeval *)icmp->icmp_data;
 42    gettimeofday(tval,NULL);//记录发送时间
 43    //校验算法
 44    icmp->icmp_cksum = cal_chksum((unsigned short *)icmp,packsize);
 45    return packsize;
 46}

 47
 48
 49//发送三个ICMP报文
 50void send_packet()
 51{
 52    int packetsize;
 53    while (nsend < 3)
 54    {
 55        nsend++;
 56        packetsize = pack(nsend);//设置ICMP报头
 57        sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr));
 58        sleep(1);//每隔一秒发送一个ICMP报文
 59    }

 60}

 61
 62//接收所有ICMP报文
 63void recv_packet()
 64{
 65    int n,fromlen;
 66    while(nreceived < nsend)
 67    {
 68        alarm(MAX_WAIT_TIME);
 69        recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,(struct sockaddr *)&from,&fromlen);//显示相关信息
 70        gettimeofday(&tvrecv,NULL);//记录接收时间
 71        unpack(recvpacket,n);//对该ICMP报文进行解析
 72        nreceived++;
 73    }

 74}

 75
 76//剥去ICMP报头
 77int unpack(char *buf,int len)
 78{
 79    int i,iphdrlen;
 80    struct ip *ip;
 81    struct icmp *icmp;
 82    struct timeval *tvsend;
 83    double rtt;
 84
 85    ip = (struct ip*) buf;
 86    iphdrlen = ip->ip_h1<<2;//求ip报头长度,即ip报头的长度标志乘4
 87    icmp = (struct icmp*)(buf+iphdrlen);//越过ip报头,指向ICMP报头
 88    len -= iphdrlen;//ICMP报头及ICMP数据报的总长度
 89    if(len < 8)
 90    {
 91        .
 92            return -1;
 93    }

 94    //确保所接收的是我所发的ICMP的回应
 95    if((icmp->icmp_type == ICMP_ECHO_REPLY) &&(icmp->icmp_id == pid))
 96    {
 97        ..
 98            printf(..);//显示相关信息
 99    }

100    else
101        return -1;
102}

103
104mian(int argc,char *argv[])
105{
106    unsigned long inaddr = 01;
107    int size = 50*1024;
108
109    //生成使用ICMP的原始套接字,其protocol是17
110    sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
111
112    //扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
113    //可能性,若无意中ping一个广播地址或多播地址,将会引起大量应答
114    setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
115    bzero(&dest_addr,sizeof(dest_addr));
116    dest_addr.sin_family = AF_INET;
117
118    send_packet();//发送所有ICMP报文
119    recv_packet();//接收所有ICMP报文
120    statistics();//进行统计
121
122    return 0;
123}

posted on 2009-12-29 14:20 lionel 阅读(408) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理