免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 964 | 回复: 0
打印 上一主题 下一主题

程序实现简单ping程序目的 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-30 19:57 |只看该作者 |倒序浏览
/************关于本文档********************************************
*filename: ping.c
*purpose:  实现简单的ping程序目的
*wrote by: fanyunfei(yinshulei5211314@yahoo.com.cn)
*date time:2007-01-30 20:03
*********************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SA struct sockaddr
#define BUFFSIZE 1024
static struct sockaddr_in dest_addr;
static int sockfd;            /** raw socket **/
static int sequence;        /**  auto initialize to 0 **/
static int counter;            /** 记录ping的次数,如果5次都没有反应则放弃 **/
void sig_alrm(int signo);        /** handler SIGALRM **/
void send_echo_request(int sockfd, SA *dest_addr);
void recv_echo_reply(int sockfd);
unsigned short check_sum(unsigned short *addr,int len);
void err_sys(const char *errmsg);
int main(int argc, char **argv)
{
    struct hostent *h;        
    struct sigaction act;        /* SIGALRM handler **/
    /** detect command line argumnet number **/
    if (argc != 2) {   
        fprintf(stderr, "Usage: ./ping \n");   
        exit(1);
    }
    /** install SIGALRM signal handler **/
    act.sa_handler = sig_alrm;
    if (sigemptyset(&act.sa_mask) == -1)
        err_sys("sigemptyset error");
    act.sa_flags = 0;
    if (sigaction(SIGALRM, &act, NULL) == -1)
        err_sys("sigaction error");
    /** create IPPROTO_ICMP raw socket **/
    if ((sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
        err_sys("socket error");
   
    if (inet_aton(argv[1], &dest_addr.sin_addr) == 0) {
        if ((h = gethostbyname(argv[1])) == NULL) {
            fprintf(stderr, "gethostbyname error: %s\n", hstrerror(h_errno));
            exit(1);
        } else
            memcpy(&dest_addr.sin_addr, h->h_addr, sizeof(struct in_addr));
    }
    /** generate SIGALRM signal for send first echo request **/
    if (kill(getpid(), SIGALRM) == -1)
        err_sys("kill error");
   
    /** read echo reply **/
    recv_echo_reply(sockfd);
    exit(0);
}
void sig_alrm(int signo)
{
    send_echo_request(sockfd, (SA *) &dest_addr);
    counter++;        /** increment counter **/
    if (counter == 5) {
        fprintf(stderr, "host is not alive...\n");
        exit(1);
    }   
        
    alarm(1);        /** 每妙钟发送一个回显请求 **/   
}
void err_sys(const char *errmsg)
{
    perror(errmsg);
   
    exit(errno);
}
void send_echo_request(int sockfd, SA *dest_addr)
{
    struct icmp *icmp;
    char buff[BUFFSIZE];
    ssize_t n;
   
    bzero(buff, sizeof(buff));
    icmp = (struct icmp *) buff;
   
    icmp->icmp_type = ICMP_ECHO;
    icmp->icmp_code = 0;
    icmp->icmp_id = getpid();
    icmp->icmp_seq = sequence++;
    icmp->icmp_cksum = 0;
    icmp->icmp_cksum = check_sum((unsigned short *) icmp, sizeof(struct icmp));
    n = sendto(sockfd, buff, sizeof(struct icmp), 0, dest_addr, 16);
    if (n != sizeof(struct icmp))
        err_sys("sendto error");
}
void recv_echo_reply(int sockfd)
{
    struct ip *ip;
    struct icmp *icmp;
    char buff[BUFFSIZE];   
    ssize_t len;
    int iphlen;            /** ip header length **/
   
    for (;;) {
        if ((len = recvfrom(sockfd, buff, BUFFSIZE, 0, NULL, NULL)) == -1) {
            if (errno = EINTR)
           
    continue;      
    /** process interrupt **/
            else
                err_sys("recvfrom error");   
        }
        
        ip = (struct ip *) buff;        /** start of IP header **/
        iphlen = ip->ip_hl ip_p != IPPROTO_ICMP) {
            fprintf(stderr, "ip datagram is not icmp\n");
            exit(1);
        }
        
        icmp = (struct icmp *) (buff + iphlen);
        if (icmp->icmp_type == ICMP_ECHOREPLY) {
            if (icmp->icmp_id != getpid()) {
                fprintf(stderr, "icmp_id error\n");
                exit(1);
            } else {
                printf("host is alive...\n");
                exit(0);
            }
        }
    } /** for **/
}
            
/* 下面是首部校验和的算法,偷了别人的 */
unsigned short check_sum(unsigned short *addr,int len)
{
    register int nleft = len;
     register int sum = 0;
     register short *w = addr;
      short answer = 0;

     while (nleft>1) {
          sum+=*w++;
          nleft-=2;
     }
     if (nleft == 1) {
          *(unsigned char *)(&answer)=*(unsigned char *)w;
          sum+=answer;
     }

     sum=(sum>>16)+(sum&0xffff);
     sum+=(sum>>16);
     answer=~sum;
     return(answer);
}
/******** 运行结果
*********                                                     
[root@localhost root]# gcc ping.c -o ping
[root@localhost root]# ./ping www.sohu.com
host is alive...
[root@localhost root]# ./ping 192.168.1.2
host is not alive...
[root@localhost root]#
                                                   
**************************/


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30746/showart_240433.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP