C语言实现ping的代码
时间: 2023-11-28 15:05:36 浏览: 62
以下是C语言实现ping的代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#define DATALEN 56
#define MAX_RECV 2048
unsigned short get_checksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned 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;
}
void build_pkt(struct icmp *icmp_pkt, int seq)
{
memset(icmp_pkt, 0, sizeof(struct icmp));
icmp_pkt->icmp_type = ICMP_ECHO;
icmp_pkt->icmp_code = 0;
icmp_pkt->icmp_seq = seq;
icmp_pkt->icmp_id = getpid();
icmp_pkt->icmp_cksum = get_checksum((unsigned short *)icmp_pkt, DATALEN + 8);
}
float diff_time(struct timeval *begin, struct timeval *end)
{
float diff = ((end->tv_sec - begin->tv_sec) * 1000.0f + (end->tv_usec -begin->tv_usec) / 1000.0f);
return diff;
}
void ping(const char *ip)
{
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0)
{
perror("socket");
exit(-1);
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = inet_addr(ip);
char recvbuf[MAX_RECV];
memset(recvbuf, 0, sizeof(recvbuf));
int seq = 1;
struct timeval begin, end;
while (seq <= 4)
{
struct icmp icmp_pkt;
build_pkt(&icmp_pkt, seq);
if (sendto(sockfd, &icmp_pkt, sizeof(icmp_pkt), 0, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("sendto");
close(sockfd);
exit(-1);
}
gettimeofday(&begin, NULL);
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(sockfd, &read_set);
int ret = select(sockfd + 1, &read_set, NULL, NULL, NULL);
if (ret < 0)
{
perror("select");
close(sockfd);
exit(-1);
}
else if (ret == 0)
{
printf("timeout\n");
}
else
{
struct sockaddr_in recv_addr;
socklen_t recv_addr_len = sizeof(recv_addr);
int nrecv = recvfrom(sockfd, recvbuf, MAX_RECV, 0, (struct sockaddr*)&recv_addr, &recv_addr_len);
if (nrecv < 0)
{
perror("recvfrom");
close(sockfd);
exit(-1);
}
gettimeofday(&end, NULL);
struct iphdr *ip_hdr = (struct iphdr *)recvbuf;
int ip_len = ip_hdr->ihl * 4;
struct icmp *icmp_pkt_reply = (struct icmp *)(recvbuf + ip_len);
if (icmp_pkt_reply->icmp_type == ICMP_ECHOREPLY)
{
printf("from %s %d bytes icmp_seq=%d ttl=%d time=%.1f ms\n", inet_ntoa(recv_addr.sin_addr), nrecv, icmp_pkt_reply->icmp_seq, ip_hdr->ttl, diff_time(&begin, &end));
}
else
{
printf("error: packet type %d\n", icmp_pkt_reply->icmp_type);
}
}
sleep(1);
seq++;
}
close(sockfd);
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("Usage: %s ip\n", argv[0]);
exit(0);
}
ping(argv[1]);
return 0;
}
```
阅读全文