#include "ping.h"
struct icmp
{
unsigned char type;
unsigned char code;
unsigned short chksum;
unsigned short id;
unsigned short seq;
unsigned long tv_sec;
unsigned long tv_usec;
unsigned char unused[DATASIZE];
};
unsigned short Ping_calchecksum(char *buffer, int len)
{
unsigned short *p = (unsigned short *)buffer;
unsigned int sum = 0;
int i = 0;
for (i = 0; i < len/2; i++)
{
sum += *p;
p++;
}
sum += (sum >> 16);
return ~sum;
}
int Ping_pack(int pack_no)
{
bzero(&g_icmp_data, sizeof(g_icmp_data));
g_icmp_data.type = PA_RESQUST;
g_icmp_data.code = 0;
g_icmp_data.chksum = 0;
g_icmp_data.id = 0;
g_icmp_data.seq = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
g_icmp_data.tv_sec = tv.tv_sec;
g_icmp_data.tv_usec = tv.tv_usec;
memset(g_icmp_data.unused, 0, DATASIZE);
g_icmp_data.chksum = Ping_calchecksum((char *)&g_icmp_data, sizeof(g_icmp_data));
return 0;
}
int Ping_mysend(int num)
{
int packetsize = 0;
int i = 0;
char ch = 0;
int rlen = 0;
for (i = 0; i < num; i++)
{
packetsize = Ping_pack(i);
if (sendto(g_sockfd, &g_icmp_data, sizeof(g_icmp_data), 0, (struct sockaddr *)&g_ser, sizeof(g_ser)) < 0)
{
perror("sendto");
continue;
}
else
{
g_begin++;
sleep(1);
}
}
return 0;
}
void* send_data(void* arg)
{
int num = 0;
if (0 == g_array[0])
{
Ping_mysend(PING_A);
}
else if (0 == strncmp(g_array, "-a", 2))
{
Ping_mysend(PING_A);
}
else if (0 == strncmp(g_array, "-t", 2))
{
Ping_mysend(PING_T);
}
else if (0 == strncmp(g_array, "-n", 2))
{
num = Ping_gettimeofn();
Ping_mysend(num);
}
return NULL;
}
int Ping_gettimeofn()
{
int sum = 0;
sum = atoi(g_nconut);
return sum;
}
int Ping_myrecv(int num)
{
int rlen = 0;
int i = 0;
char ch = 0;
int ret = 0;
while (i < num)
{
memset(g_buffer_recv, 0, sizeof(g_buffer_recv));
rlen = recv(g_sockfd, g_buffer_recv, sizeof(g_buffer_recv), 0);
if (rlen < 0)
{
printf("fail to recv!\n");
continue;
}
i++;
ret = Ping_unpack(rlen);
if (-1 == ret)
{
continue;
}
else
{
g_end++;
}
}
return 0;
}
void* recv_data(void *arg)
{
int num = 0;
if (0 == g_array[0])
{
Ping_myrecv(PING_A);
}
else if (0 == strncmp(g_array, "-a", 2))
{
Ping_myrecv(PING_A);
}
else if (0 == strncmp(g_array, "-t", 2))
{
Ping_myrecv(PING_T);
}
else if (0 == strncmp(g_array, "-n", 2))
{
num = Ping_gettimeofn();
Ping_myrecv(num);
}
return NULL;
}
int Ping_unpack(int len)
{
double rtt = 0;
struct timeval tv_cur;
struct ip *myip;
struct icmp *myicmp;
int ipsize = 0;
char *recv_ip = NULL;
myip = (struct ip*)g_buffer_recv;
ipsize = (myip->ip_hl)<<2;
recv_ip = (char *)inet_ntoa(myip->ip_src);
len -= ipsize;
myicmp = (struct icmp *)(g_buffer_recv + ipsize);
if (len < UP_ICMPHEAD)
{
perror("ICMP packets length is less than 8\n");
return -1;
}
else if(strcmp(g_ip, recv_ip))
{
return -1;
}
else if (myicmp->type != 0)
{
return -1;
}
else
{
gettimeofday(&tv_cur, NULL);
rtt = (tv_cur.tv_sec - g_icmp_data.tv_sec)*1000 + (tv_cur.tv_usec - g_icmp_data.tv_usec)/1000.0f;
g_totaltime += rtt;
if (rtt > g_maxtime)
{
g_maxtime = rtt;
}
if (rtt < g_mintime)
{
g_mintime = rtt;
}
printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%0.1fms\n", g_datalen + UP_ICMPHEAD, inet_ntoa(g_ser.sin_addr), g_end, myip->ip_ttl, rtt);
}
return 0;
}
void sig_int(int signo)
{
double perce = 0;
perce = (g_begin - g_end) / g_begin;
printf("---ping %s is complete--- \n %d was sended and %d was received, %0.1lf%%packet loss, time %0.1fms rtt\n min/avg/max = %0.1f/%0.1f/%0.1f ms \n", g_tmpbuff, g_begin, g_end, perce * 100 , g_totaltime, g_mintime, g_totaltime/g_begin, g_maxtime);
exit(0);
}
int main(int argc, char *argv[])
{
double number = 0;
struct hostent *ent = NULL;
pthread_t pid1 = 0, pid2 = 0;
signal(SIGINT, sig_int);
snprintf(g_tmpbuff, sizeof(g_tmpbuff), "%s", argv[1]);
if (argc < 2)
{
return -1;
}
if (argv[1] == NULL)
{
perror("fail to ping!");
return -1;
}
if (argc > 2)
{
memset(g_array, 0, sizeof(g_array));
memset(g_nconut, 0, sizeof(g_nconut));
snprintf(g_array, sizeof(g_array), "%s", argv[2]);
}
if (argc > 3)
{
if (0 == strncmp(g_array, "-n", 2))
{
snprintf(g_nconut, sizeof(g_nconut), "%s", argv[3]);
}
}
ent = gethostbyname(argv[1]);
if (NULL == ent)
{
printf("ping: unknown host %s\n", argv[1]);
exit(-1);
}
inet_ntop(AF_INET, ent->h_addr, g_ip, sizeof(g_ip));
g_sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
bzero(&g_ser, sizeof(g_ser));
g_ser.sin_family = AF_INET;
inet_pton(AF_INET, g_ip, &g_ser.sin_addr);
printf("PING %s (%s) %d bytes of data.\n", g_tmpbuff, g_ip, g_datalen);
if(pthread_create(&pid1, NULL, send_data, NULL) < 0)
{
perror("pthread_create");
return -1;
}
if(pthread_create(&pid2, NULL, recv_data, NULL) < 0)
{
perror("pthread_create");
return -1;
}
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
number = (g_begin - g_end) * 100 / g_begin;
printf("---ping %s is complete--- \n %d was sended and %d was received, %0.1lf%%packet loss, time %0.1fms \n min/avg/max = %0.1f/%0.1f/%0.1f ms \n", argv[1], g_begin, g_end, number, g_totaltime, g_mintime, g_totaltime/g_begin, g_maxtime);
close(g_sockfd);
return 0;
}
头文件
#ifndef PING__H_
#define PING__H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/time.h>
#include <signal.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <pthread.h>
#define BUFFER_SIZE 512
#define MAX_SIZE 56
#define ARRAY_SIZE 12
#define NCONUT_SIZE 12
#define ARGV1 128
#define MINSIZE 1000
#define DATASIZE 48
#define PING_A 4
#define PING_T 100
#define UP_ICMPHEAD 8
#define PA_RESQUST 8
struct icmp g_icmp_data;
struct sockaddr_in g_ser;
int g_begin = 0;
int g_end = 0;
int g_sockfd = 0;
char g_buffer_recv[BUFFER_SIZE] = {0};
int g_datalen = MAX_SIZE;
char g_array[ARRAY_SIZE] = {0};
char g_nconut[NCONUT_SIZE] = {0};
char g_tmpbuff[ARGV1] = {0};
double g_totaltime = 0;
double g_maxtime = 0;
double g_mintime = MINSIZE;
char g_ip[32] = {0};
int Ping_compareInput();
int Ping_gettimeofn();
unsigned short Ping_calchecksum(char *buffer, int len);
int Ping_pack(int pack_no);
int Ping_mysend();
int Ping_myrecv();
int Ping_unpack(int len);
#endif