一个基本的ping程序C代码

本文介绍了一个简单的Ping程序C代码实现过程。该程序能在Linux环境下运行,通过发送ICMP_ECHO请求来测试目标主机是否可达,并接收ICMP_ECHOREPLY响应以确认目标主机存活状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在看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 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值