⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 108.htm

📁 unix高级编程原吗
💻 HTM
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>123</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center">               ● UNIX网络编程                       (BM: clown)                </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p   align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="54.htm">上一层</a>][<a href="109.htm">下一篇</a>]
<hr><p align="left"><small>发信人: clown (梧桐叶), 信区: UNP <br>

标  题: 模仿unp写的一个简单的ping程序 <br>

发信站: UNIX编程 (2001年11月15日19:53:55 星期四), 站内信件 <br>

  <br>

#include <stdio.h> <br>

#include <unistd.h> <br>

#include <stdlib.h> <br>

#include <sys/types.h> <br>

#include <sys/socket.h> <br>

#include <arpa/inet.h> <br>

#include <sys/time.h> <br>

#include <netinet/in.h> <br>

#include <netinet/ip.h> <br>

#include <netinet/ip_icmp.h> <br>

#include <signal.h> <br>

#include <netdb.h> <br>

#include <errno.h> <br>

#include <string.h> <br>

  <br>

#define SIZE 60 <br>

  <br>

int datalen = 8;    //data that goes with ICMP echo request <br>

int sockfd; <br>

int sockfd; <br>

struct sockaddr_in saddr; <br>

int socklen; <br>

  <br>

void sig_alarm(int); <br>

void proc(char *, int, struct timeval *); <br>

void sendicmp(); <br>

unsigned short checksum(unsigned short *, int); <br>

  <br>

int main(int argc, char **argv) <br>

{ <br>

    int clilen, n; <br>

    struct hostent *host; <br>

    char dest[16], recvbuf[SIZE]; <br>

    struct sockaddr cli; <br>

    struct timeval tv; <br>

  <br>

    if(argc != 2) { <br>

        printf("Usage: %s <host>\n", argv[0]); <br>

        exit(1); <br>

    } <br>

    errno = 0; <br>

    h_errno = 0; <br>



  <br>

    if((host = gethostbyname(argv[1])) == NULL) { <br>

        herror("gethostbyname"); <br>

        exit(1); <br>

    } <br>

    if(host->h_addrtype != AF_INET) { <br>

        printf("Unsupported net family %d\n", host->h_addrtype); <br>

        exit(1); <br>

    } <br>

    if(inet_ntop(AF_INET, host->h_addr, dest, sizeof(dest)) == NULL) { <br>

        perror("inet_ntop"); <br>

        exit(1); <br>

    } <br>

  <br>

    //get the dest address, for the sendicmp() <br>

    memset(&saddr, 0, sizeof(struct sockaddr_in)); <br>

    saddr.sin_family = AF_INET; <br>

    memcpy((void *)&saddr.sin_addr, host->h_addr, host->h_length); <br>

    socklen = sizeof(struct sockaddr_in); <br>

  <br>

    printf("Ping %s(%s): %d bytes data\n", host->h_name, dest, datalen); <br>

    if((sockfd=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { <br>



        perror("socket"); <br>

        exit(1); <br>

    } <br>

    setuid(getuid());   //don't need root privilege any more. <br>

    if(signal(SIGALRM, sig_alarm) == SIG_ERR) { <br>

        perror("signal"); <br>

        exit(1); <br>

    } <br>

    sig_alarm(SIGALRM); <br>

    while(1) { <br>

        clilen = sizeof(struct sockaddr); <br>

        memset(recvbuf, 0, sizeof(recvbuf)); <br>

        n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, &cli, &clilen); <br>

        if(n < 0) { <br>

            if(errno == EINTR) <br>

                continue; <br>

            else { <br>

                perror("recvfrom"); <br>

                exit(1); <br>

            } <br>

        } <br>

        if(gettimeofday(&tv, NULL) == -1) { <br>



            perror("gettimeofday"); <br>

            exit(1); <br>

        } <br>

        //printf("a packet received by SOCK_RAW IPPROTO_ICMP\n"); <br>

        proc(recvbuf, n, &tv); <br>

    } <br>

    return 0; <br>

} <br>

  <br>

void sig_alarm(int signo) <br>

{ <br>

    sendicmp(); <br>

    alarm(1); <br>

    return; <br>

} <br>

  <br>

/* <br>

 * <br>

 * the packet send and received <br>

 * <br>

|---------------------len----------------------------| <br>

|-----------hlen-----------|--------icmplen----------| <br>



  <br>

|IPv4 header | IPv4 option | ICMP header | ICMP data | <br>

  <br>

|----20B-----|-----0~40B---|-----8B------| <br>

* <br>

*/ <br>

  <br>

void proc(char *ptr, int len, struct timeval *tvrecv) <br>

{ <br>

    int hlen, icmplen; <br>

    double rtt; <br>

    struct ip *ip; <br>

    struct icmp *icmp; <br>

    struct timeval *tvsend; <br>

    pid_t pid; <br>

    char src[16], dest[16]; <br>

  <br>

    void timeval_sub(struct timeval *, struct timeval *); <br>

  <br>

    pid = getpid(); <br>

    ip = (struct ip *)ptr; <br>

    hlen = ip->ip_hl<<2;    //length of IP header <br>



    if(inet_ntop(AF_INET, (void *)&ip->ip_src, src, sizeof(src)) == NULL) { <br>

        perror("inet_ntop"); <br>

        exit(1); <br>

    } <br>

    if(inet_ntop(AF_INET, (void *)&ip->ip_dst, dest, sizeof(dest)) == NULL) { <br>

        perror("inet_ntop"); <br>

        exit(1); <br>

    } <br>

  <br>

    icmp = (struct icmp *)(ptr + hlen); <br>

    if((icmplen = len-hlen) < 8) { <br>

        printf("icmplen: %d < 8\n", icmplen); <br>

        exit(1); <br>

    } <br>

    if(icmp->icmp_type == ICMP_ECHOREPLY) { <br>

        if(icmp->icmp_id != pid)  //not a response to our ECHO_REQUEST <br>

            return; <br>

        if(icmplen < 16) { <br>

            //icmp header: type(1B), code(1B), checksum(2B), <br>

            //      id(2B), seq(2B); <br>

            //data: time(8B); <br>

            printf("icmplen: %d < 16\n", icmplen); <br>



            exit(1); <br>

        } <br>

        tvsend = (struct timeval *)icmp->icmp_data; <br>

        timeval_sub(tvrecv, tvsend); <br>

        rtt = tvrecv->tv_sec*1000.0 + tvrecv->tv_usec/1000.0; //ms <br>

        printf("%d bytes from %s: seq=%d, ttl=%d, rtt=%.3fms\n", <br>

                icmplen, src, icmp->icmp_seq, ip->ip_ttl, rtt); <br>

    } <br>

    /* <br>

    else { <br>

        printf("%d bytes from %s to %s: type=%d, code=%d\n", icmplen, <br>

                src, dest, icmp->icmp_type, icmp->icmp_code); <br>

    } <br>

    */ <br>

    return; <br>

} <br>

  <br>

void timeval_sub(struct timeval *recv, struct timeval *send) <br>

{ <br>

    if((recv->tv_usec -= send->tv_usec) < 0) { <br>

        recv->tv_sec--; <br>

        recv->tv_usec += 1000000; <br>



    } <br>

    recv->tv_sec -= send->tv_sec; <br>

    return; <br>

} <br>

  <br>

void sendicmp() <br>

{ <br>

    static unsigned short nsend = 0; <br>

    int len; <br>

    struct icmp *icmp; <br>

    unsigned char sendbuf[SIZE]; <br>

  <br>

    memset(sendbuf, 0, sizeof(sendbuf)); <br>

  <br>

    icmp = (struct icmp *)sendbuf; <br>

    icmp->icmp_type = ICMP_ECHO; <br>

    icmp->icmp_code = 0; <br>

    icmp->icmp_id = getpid(); <br>

    icmp->icmp_seq = nsend++; <br>

  <br>

    if(gettimeofday((struct timeval *)icmp->icmp_data, NULL) == -1) { <br>

        perror("gettimeofday"); <br>



        exit(1); <br>

    } <br>

  <br>

    len = 8 + datalen;  //checksum ICMP header and data <br>

    //Does checksum need change to network byte order? <br>

    //I don't know, and it seems no matter. <br>

    icmp->icmp_cksum = checksum((unsigned short *)icmp, len); <br>

  <br>

    //printf("send icmp packet %d\n", nsend); <br>

    sendto(sockfd, sendbuf, len, 0, (struct sockaddr *)&saddr, socklen); <br>

    return; <br>

} <br>

  <br>

unsigned short checksum(unsigned short *addr, int len) <br>

{ <br>

    int nleft = len; <br>

    int sum = 0; <br>

    unsigned short *w = addr; <br>

    unsigned short answer = 0;  //16 bits <br>

  <br>

    while(nleft > 1) { <br>

        sum += *w++; <br>



        nleft -= 2; <br>

    } <br>

    if(nleft == 1) { <br>

        //the lower 8 bits of answer will be filled with zero <br>

        *(unsigned char *)(&answer) = *(unsigned char *)w; <br>

        sum += answer; <br>

    } <br>

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

    sum += (sum >> 16); <br>

    answer = ~sum; <br>

    //printf("answer %d\n", answer); <br>

    return answer; <br>

} <br>

  <br>

  <br>

-- <br>

易朽的是生命,似那转瞬即谢的花朵;然而永存的,是对未来的渴望, <br>

是那生生世世传递下来的,不朽的,生的激情。每一朵勇敢开放的花, <br>

都是一个死亡唇边的微笑。 <br>

※ 来源:·UNIX编程 apue.dhs.org·[FROM: 202.114.1.61] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="54.htm">上一层</a>][<a href="109.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -