文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>程序实现简单ping程序目的

程序实现简单ping程序目的

时间:2007-01-30  来源:只爱殷澍蕾

/************关于本文档********************************************
*filename: ping.c
*purpose:  实现简单的ping程序目的
*wrote by: fanyunfei([email protected])
*date time:2007-01-30 20:03
*********************************************************************/

#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>

#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 <Domain name or IP address>\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 << 2;        /** length of IP header **/
        if (ip->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]#
                                                   
**************************/
 
相关阅读 更多 +
排行榜 更多 +
小小盗贼正版下载

小小盗贼正版下载

休闲益智 下载
骨骼实验室手机版下载安装

骨骼实验室手机版下载安装

飞行射击 下载
pubgtool画质助手官方正版下载

pubgtool画质助手官方正版下载

游戏工具 下载