|
- // file: ping.cpp
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <time.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/ip_icmp.h>
- #include <sys/time.h>
- #include <string.h>
- #include <signal.h>
- #include <netdb.h>
- int fd = 0;
- struct addrinfo *ai = NULL;
- int pid = 0;
- struct addrinfo *host_serv(const char *host, const char *serv, int family, int socktype)
- {
- struct addrinfo hints, *res = NULL;
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_family = family;
- hints.ai_socktype = socktype;
- int n = getaddrinfo(host, serv, &hints, &res);
- if (n != 0)
- return NULL;
- return res;
- }
- void tv_sub(struct timeval *out, struct timeval *in)
- {
- out->tv_usec -= in->tv_usec;
- if (out->tv_usec < 0) {
- --out->tv_sec;
- out->tv_usec += 1000000;
- }
- out->tv_sec -= in->tv_sec;
- }
- unsigned short in_cksum(unsigned short *addr, int len)
- {
- int left = len;
- int sum = 0;
- unsigned short *ptr = addr;
- while (left > 1) {
- sum += *ptr++;
- left -= 2;
- }
-
- unsigned short answer = 0;
- if (left == 1) {
- *(unsigned char *)(&answer) = *(unsigned char *)ptr;
- sum += answer;
- }
-
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- answer = ~sum;
- return answer;
- }
- void recv_ping(char *ptr, ssize_t len, struct timeval *tvrecv)
- {
- if (len < sizeof(struct ip))
- return;
- struct ip *ip_ptr = (struct ip *)ptr;
- int ip_hlen = (ip_ptr->ip_hl << 2);
- struct icmp *icmp_ptr = (struct icmp *)(ptr + ip_hlen);
- int icmp_len = len - ip_hlen;
- if (icmp_len < 8)
- return;
- if (icmp_ptr->icmp_type == ICMP_ECHOREPLY) {
- if (icmp_ptr->icmp_id != pid)
- return;
- if (icmp_len < 16)
- return;
- struct timeval *tvsend = (struct timeval *)icmp_ptr->icmp_data;
- tv_sub(tvrecv, tvsend);
- double rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec / 1000.0;
-
- printf("%d bytes: seq=%u, ttl=%d, rtt=%.3fms\n",
- icmp_len,
- icmp_ptr->icmp_seq,
- ip_ptr->ip_ttl,
- rtt);
- }
- }
- void send_ping(int fd, struct addrinfo *addr, int pid)
- {
- static int seq = 0;
- char buff[1024];
- struct icmp *icmp_ptr = (struct icmp *)buff;
- icmp_ptr->icmp_type = ICMP_ECHO;
- icmp_ptr->icmp_code = 0;
- icmp_ptr->icmp_id = pid;
- icmp_ptr->icmp_seq = ++seq;
- memset(icmp_ptr->icmp_data, 0xa5, 56);
-
- gettimeofday((struct timeval *)icmp_ptr->icmp_data, NULL);
- int len = sizeof(timeval) + 56;
- icmp_ptr->icmp_cksum = in_cksum((u_short*)icmp_ptr, len);
- sendto(fd, buff, len, 0, addr->ai_addr, addr->ai_addrlen);
- }
- void sig_alarm(int signo)
- {
- send_ping(fd, ai, pid);
- alarm(1);
- }
- int main(int argc, char *argv[])
- {
- if (argc != 2)
- {
- printf("Usage: %s <ip>\n", argv[0]);
- return -1;
- }
- fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- if (fd < 0)
- {
- printf("Failed to create socket!\n");
- return -1;
- }
- ai = host_serv(argv[1], NULL, 0, 0);
- if (!ai)
- {
- printf("Failed to get address of %s\n", argv[1]);
- return -1;
- }
-
- pid = getpid();
- signal(SIGALRM, sig_alarm);
- sig_alarm(SIGALRM);
-
- char buff[1024];
- char addr[1024];
- for (;;)
- {
- socklen_t len = sizeof(ai->ai_addrlen);
- ssize_t n = recvfrom(fd, buff, sizeof(buff), 0, (sockaddr*)addr, &len);
- if (n > 0)
- {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- recv_ping(buff, n, &tv);
- }
- }
- return 0;
- }
复制代码
编译:#g++ -g -o ping ping.cpp |
|