一个基本的ping程序C代码

在看Steven的TCP/IP Illustrated, V1, 改了一个非常简单的ping echo的C代码,在linux上编译通,就当学习吧。

 

       1  #include  < stdio.h >
      
2  #include  < sys / types.h >
      
3  #include  < sys / socket.h >
      
4  #include  < arpa / inet.h >
      
5  #include  < netdb.h >
      
6  #include  < netinet / in .h >
      
7  #include  < netinet / ip_icmp.h >
      
8  #include  < signal.h >
      
9  #include  < errno.h >
     
10
     
11   static   const   int  DEFDATALEN  =   56 ;
     
12   static   const   int  MAXIPLEN  =   60 ;    //  max len of ip header, 15 * 4
      13   static   const   int  MAXICMPLEN  =   76 //  max len of icmp header
      14
     
15   static   void  noresp( int );
     
16   static   void  ping( const   char   * );
     
17  u_short in_cksum(u_short  * int );
     
18   void  usage( void );
     
19
     
20   int  main( int  argc,  char   * argv[])
     
21   {
     
22
     
23     if(argc != 2)
     
24         usage();
     
25     ping(*++argv);
     
26 }

     
27
     
28   static   void  noresp( int  ign)
     
29   {   // signal fun
     30     printf("No response ");
     
31     exit(0);
     
32 }

     
33
     
34   static   void  ping( const   char   * host)
     
35   {
     
36     struct hostent *hp;
     
37     struct sockaddr_in target;
     
38     struct icmp *packet;
     
39     char outpack[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
     
40     int sock, c;
     
41
     
42     if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
     
43     {
     
44         perror("socket");
     
45         exit(1);
     
46     }

     
47
     
48     memset(&target, 0sizeof(struct sockaddr_in));
     
49     target.sin_family = AF_INET;
     
50     if(inet_aton(host, (struct in_addr*)&target.sin_addr.s_addr)== 0)
     
51     {
     
52         hp = gethostbyname(host);
     
53         if(!hp)
     
54         {
     
55             fprintf(stderr, "ping: unknown host %s ", host);
     
56             exit(1);
     
57         }

     
58         memcpy(&target.sin_addr, hp->h_addr, 4);
     
59     }

     
60
     
61     memset(outpack, 0sizeof(outpack));
     
62     packet = (struct icmp*)outpack;
     
63     packet->icmp_type = ICMP_ECHO;
     
64     packet->icmp_id = getpid();
     
65
     
66     // checksum
     67     packet->icmp_cksum = in_cksum((u_short *)packet, sizeof(outpack));
     
68     c = sendto(sock, packet, sizeof(outpack), 0, (struct sockaddr*)&target, sizeof(struct sockaddr_in));
     
69     if(c < 0 || c != sizeof(outpack))
     
70     {
     
71         perror("sendto");
     
72         exit(1);
     
73     }

     
74
     
75     // set a timer
     76     signal(SIGALRM, noresp);
     
77     alarm(5);
     
78     while(1)
     
79     {
     
80         struct sockaddr_in from;
     
81         size_t fromlen = sizeof(struct sockaddr_in);
     
82
     
83         if (( c = recvfrom(sock, outpack, sizeof(outpack), 0,
     
84                     (struct sockaddr*)&from, &fromlen)) < 0)
     
85         {
     
86             if (errno == EINTR)
     
87                 continue;
     
88             perror("recvfrom");
     
89             continue;
     
90         }

     
91
     
92         if (c >= 76)
     
93         {   // the request ip header is in the reply pack, skip
     94             struct iphdr *iphdr = (struct iphdr *)outpack;
     
95             packet = (struct icmp *)(outpack + (iphdr->ihl<<2));
     
96             if (packet->icmp_type == ICMP_ECHOREPLY)
     
97                 break;
     
98         }

     
99     }

    
100     printf("%s is alive ", inet_ntoa(target.sin_addr));
    
101     return;
    
102 }

    
103
    
104   void  usage( void )
    
105   {
    
106     struct sockaddr_in whereto;
    
107     fprintf(stderr, "Usage: prg host ");
    
108     exit(1);
    
109 }

    
110
    
111  u_short in_cksum(u_short  * addr,  int  len)
    
112   {
    
113     int sum = 0, nleft = len;
    
114     u_short *= addr, ret;
    
115
    
116     while(nleft > 1)
    
117     {
    
118         sum += *w++;
    
119         nleft -= 2;
    
120     }

    
121     if(nleft == 1)
    
122         sum += htons(*(u_char*)w << 8);
    
123
    
124     sum = (sum >> 16+ (sum & 0xffff);
    
125     sum += sum >> 16;
    
126     ret = ~sum;
    
127     return ret;
    
128 }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值