linux 程序实现 ping,LINUX下 ping的源代码 C实现

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define

PACKET_SIZE 4096

#define MAX_WAIT_TIME 5

#define MAX_NO_PACKETS 3

#define

_DEBUG_ 1

char sendpacket[PACKET_SIZE];

char recvpacket[PACKET_SIZE];

int sockfd, datalen = 8;

int nsend = 0, nreceived = 0;

struct sockaddr_in dest_addr;

pid_t pid;

struct sockaddr_in from;

struct timeval tvrecv;

void statistics(int signo);

unsigned short cal_chksum(unsigned short *addr,int len);

int pack(int pack_no);

void send_packet(void);

void recv_packet(void);

int unpack(char *buf,int len);

void tv_sub(struct timeval *out,struct timeval *in);

void statistics(int signo)

{

printf("\n--------------------PING

statistics-------------------\n");

printf("%d packets transmitted, %d received , %%%d lost\n",

nsend, nreceived, (nsend-nreceived)/nsend*100);

close(sockfd);

printf("catch signal\n");

exit(1);

}

unsigned short cal_chksum(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)

{

/

int pack(int pack_no)

{

int packsize;

struct icmp *icmp;

struct timeval *tval;

icmp = (struct icmp*)sendpacket;

icmp->icmp_type = ICMP_ECHO;

icmp->icmp_code = 0;

icmp->icmp_cksum = 0;

icmp->icmp_seq = pack_no;

icmp->icmp_id = pid;

packsize = 8 + datalen;

tval = (struct timeval *)icmp->icmp_data;

gettimeofday(tval,

NULL);

#if _DEBUG_

//printf("sec = %ld, usec = %ld\n",

tval->tv_sec, tval->tv_usec);

#endif

icmp->icmp_cksum = cal_chksum( (unsigned short

*)icmp,packsize);

#if _DEBUG_

printf("cksum = 0x%x\n", icmp->icmp_cksum);

#endif

return packsize;

}

void send_packet()

{

int packetsize;

{

nsend++;

packetsize = pack(nsend);

#if _DEBUG_

//printf("nsend = %d, packetsize = %d\n", nsend,

packetsize);

#endif

if (sendto(sockfd, sendpacket, packetsize, 0,

(struct sockaddr *)&dest_addr,

sizeof(dest_addr)) < 0)

{

perror("sendto error");

return;

}

//usleep(1000);

}

}

void recv_packet()

{

int n, count = 0;

socklen_t fromlen;

extern int errno;

//fromlen = sizeof(from);

while ( count < 2)

{

count++;

fromlen = sizeof(from);

alarm(MAX_WAIT_TIME);

if ((n = recvfrom(sockfd, recvpacket, sizeof(recvpacket),

0,

(struct sockaddr *)&from,

&fromlen)) < 0)

{

if (errno == EINTR)

{

printf("errno == EINTR\n");

continue;

}

perror("recvfrom error");

continue;

}

alarm(0);

printf("n = %d\n", n);

//gettimeofday(&tvrecv, NULL);

if (unpack(recvpacket, n) == -1) continue;

nreceived++;

break;

}

return;

}

int unpack(char *buf,int len)

{

int iphdrlen;

struct ip *ip;

struct icmp *icmp;

struct timeval *tvsend;

double rtt;

ip = (struct ip *)buf;

iphdrlen =

ip->ip_hl<<2;

icmp = (struct icmp *)(buf+iphdrlen);

len -=

iphdrlen;

if (len <

8)

{

printf("ICMP packets\'s length is less than 8\n");

return -1;

}

//printf("%d, icmp_id = %d\n", ICMP_ECHOREPLY,

icmp->icmp_id);

if ((icmp->icmp_type == ICMP_ECHOREPLY)

&& (icmp->icmp_id ==

pid))

{

gettimeofday(&tvrecv, NULL);

#if _DEBUG_

//printf("sec = %ld, usec = %ld\n", tvrecv.tv_sec,

tvrecv.tv_usec);

#endif

tvsend = (struct timeval *)icmp->icmp_data;

tv_sub(&tvrecv, tvsend);

rtt = tvrecv.tv_sec*1000 + (double)tvrecv.tv_usec/1000;

printf("%d byte from %s: icmp_seq=%u ttl=%d rtt=%.3f

ms\n",

len, inet_ntoa(from.sin_addr), icmp->icmp_seq,

ip->ip_ttl, rtt);

return 1;

}

else return -1;

}

int main(int argc,char *argv[])

{

struct hostent *host;

struct protoent *protocol;

unsigned long inaddr = 0l;

//int waittime = MAX_WAIT_TIME;

memset(sendpacket, 'a', sizeof(sendpacket));

int size = 50*1024;

if (argc < 2)

{

printf("usage:%s hostname/IP address\n",argv[0]);

exit(1);

}

if ((protocol = getprotobyname("icmp")) == NULL)

{

perror("getprotobyname");

exit(1);

}

#if _DEBUG_

printf("the protocol number used is %d\n",

protocol->p_proto);

#endif

if ((sockfd = socket(AF_INET, SOCK_RAW,

protocol->p_proto)) < 0)

{

perror("socket error");

exit(1);

}

//setuid(getuid());

setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,

&size, sizeof(size));

bzero(&dest_addr,sizeof(dest_addr));

dest_addr.sin_family = AF_INET;

if ((inaddr = inet_addr(argv[1])) == INADDR_NONE)

{

if ((host = gethostbyname(argv[1])) == NULL)

{

perror("gethostbyname error");

exit(1);

}

memcpy( (char *)&dest_addr.sin_addr,

host->h_addr, host->h_length);

}

else

{

memcpy( (char *)&dest_addr.sin_addr.s_addr,

(char *)&inaddr, sizeof(inaddr));

}

pid = getpid();

printf("PING %s(%s): %d bytes data in ICMP

packets.\n",argv[1],

inet_ntoa(dest_addr.sin_addr),datalen);

signal(SIGALRM, statistics);

while (nsend < MAX_NO_PACKETS)

{

send_packet();

recv_packet();

sleep(1);

}

statistics(SIGALRM);

return 0;

}

void tv_sub(struct timeval *out, struct timeval *in)

{

if ((out->tv_usec -=

in->tv_usec) < 0)

{

--out->tv_sec;

out->tv_usec += 1000000;

}

out->tv_sec -= in->tv_sec;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值