鱼人下一代 任务:--Linux下的ping源码
来源:百度文库 编辑:九乡新闻网 时间:2024/03/29 23:50:28
已修改
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IP_HEAD_LEN 20
#define ICMP_LEN 8
void send_icmp(int);
void recv_icmp(void);
unsigned short check_sum(unsigned short *addr, int len);
int sockfd;
char sendbuf[150];
char recvbuf[150];
struct sockaddr_in destaddr;
int my_icmp_id = 0;
int my_sequence = 400;
int send_num = 0;
int recv_num = 0;
float total_delay = 0.0;
/* Check Sum */
unsigned short check_sum(unsigned short *addr, int len)
{
int nleft = len;
unsigned short *w = addr;
int sum = 0;
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); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
void stat()
{
if(send_num)
{
printf("\n----ping statistics summerized by Digger----\n");
printf("%d packets sent, %d packets received, %.2f%% lost\n",
send_num,recv_num,(float)(send_num-recv_num)/(float)send_num*100);
}
exit(0);
}
void send_icmp(int signo)
{
int len;
struct icmphdr *my_icmp = (struct icmphdr *)(sendbuf);
my_icmp->type = ICMP_ECHO;
my_icmp->code = 0;
my_icmp->checksum = 0;
(my_icmp->un).echo.id = my_icmp_id;
(my_icmp->un).echo.sequence = my_sequence;
gettimeofday((struct timeval *)(my_icmp+1), NULL); //after plus 1, we get the address of icmp data because of the rule of pointer plus
len = sizeof(struct timeval)+ICMP_LEN;
my_icmp->checksum = check_sum((unsigned short *)sendbuf, len);
len = sendto(sockfd, sendbuf, len , 0, (struct sockaddr *)&destaddr, sizeof(struct sockaddr));
if (len <= 0)
{
perror("fail to send!!\n");
exit(1);
}
++send_num;
++my_sequence;
printf("sendto -----%s-----\n", inet_ntoa(destaddr.sin_addr));
alarm(1);
}
void recv_icmp(void)
{
struct timeval *time_now;
struct timeval *time_send;
struct timeval now;
struct ip *my_ip;
struct icmphdr *my_icmp;
int n;
int icmp_len;
float delay;
memset(recvbuf, '\0', 150); //应该这样做 初始化
while(1)
{
n = recvfrom(sockfd, recvbuf, 150, 0, NULL, NULL);
if (n < 0)
{
//perror("sth is wrong!\n");
continue;
}
my_ip = (struct ip *)(recvbuf);
my_icmp = (struct icmphdr *)(recvbuf+IP_HEAD_LEN); // 一定要注意,要加20(ip packet header);
icmp_len = n;
if (icmp_len < 8)
{
perror("echo is not right!\n");
continue;
}
if (ICMP_ECHOREPLY == my_icmp->type)
{
if ((my_icmp->un).echo.id != my_icmp_id)
{
printf("the id is not right!\n");
continue;
}
gettimeofday(&now, NULL);
time_now = &now;
time_send = (struct timeval *)(my_icmp+1);
time_now->tv_sec -= time_send->tv_sec;
time_now->tv_usec -= time_send->tv_usec;
delay = time_now->tv_sec * 1000.0 + time_now->tv_usec/1000.0;
++recv_num;
total_delay += delay;
printf("%d bytes received and delay is %fms \n", icmp_len, delay);
}
}
}
int main(int argc, char **argv)
{
if (2 != argc)
{
perror("using : ping IP\n");
exit(1);
}
if (-1 == (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)))
{
perror("faild to socket\n");
exit(1);
}
my_icmp_id = getpid() + 10;
bzero(&destaddr, sizeof(struct sockaddr_in));
destaddr.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &destaddr.sin_addr.s_addr);
bzero(sendbuf, 150);
sigset(SIGINT,stat);
signal(SIGALRM, send_icmp);
alarm(1);
recv_icmp();
}