⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <ip.h>typedef struct Icmp Icmp;struct Icmp{	uchar	vihl;		/* Version and header length */	uchar	tos;		/* Type of service */	uchar	length[2];	/* packet length */	uchar	id[2];		/* Identification */	uchar	frag[2];	/* Fragment information */	uchar	ttl;		/* Time to live */	uchar	proto;		/* Protocol */	uchar	ipcksum[2];	/* Header checksum */	uchar	src[4];		/* Ip source */	uchar	dst[4];		/* Ip destination */	uchar	type;	uchar	code;	uchar	cksum[2];	uchar	icmpid[2];	uchar	seq[2];	uchar	data[1];};enum{			/* Packet Types */	EchoReply	= 0,	Unreachable	= 3,	SrcQuench	= 4,	EchoRequest	= 8,	TimeExceed	= 11,	Timestamp	= 13,	TimestampReply	= 14,	InfoRequest	= 15,	InfoReply	= 16,	ICMP_IPSIZE	= 20,	ICMP_HDRSIZE	= 8,	MAXMSG		= 32,	SLEEPMS		= 1000,};typedef struct Req Req;struct Req{	ushort	seq;	// sequence number	vlong	time;	// time sent	vlong	rtt;	int	ttl;	int	replied;	Req	 *next;};Req	*first;		// request listReq	*last;		// ...Lock	listlock;char *argv0;int debug;int quiet;int lostonly;int lostmsgs;int rcvdmsgs;int done;int rint;vlong sum;ushort firstseq;int addresses;int flood;void usage(void);void lost(Req*, Icmp*);void reply(Req*, Icmp*);#define SECOND 1000000000LL#define MINUTE (60LL*SECOND)static voidcatch(void *a, char *msg){	USED(a);	if(strstr(msg, "alarm"))		noted(NCONT);	else if(strstr(msg, "die"))		exits("errors");	else		noted(NDFLT);}voidclean(ushort seq, vlong now, Icmp *ip){	Req **l, *r;	lock(&listlock);	last = nil;	for(l = &first; *l; ){		r = *l;		if(ip && r->seq == seq){			r->rtt = now-r->time;			r->ttl = ip->ttl;			reply(r, ip);		}		if(now-r->time > MINUTE){			*l = r->next;			r->rtt = now-r->time;			if(ip)				r->ttl = ip->ttl;			if(r->replied == 0)				lost(r, ip);			free(r);		}else{			last = r;			l = &(r->next);		}	}	unlock(&listlock);}voidsender(int fd, int msglen, int interval, int n){	char buf[64*1024+512];	Icmp *ip;	int i, extra;	Req *r;	ushort seq;	ip = (Icmp*)buf;	srand(time(0));	firstseq = seq = rand();	for(i = 32; i < msglen; i++)		buf[i] = i;	ip->type = EchoRequest;	ip->code = 0;	for(i = 0; i < n; i++){		if(i != 0){			extra = rint? nrand(interval): 0;			sleep(interval + extra);		}		r = malloc(sizeof *r);		if(r != nil){			hnputs(ip->seq, seq);			r->seq = seq;			r->next = nil;			r->replied = 0;			r->time = nsec();	/* avoid early free in reply! */			lock(&listlock);			if(first == nil)				first = r;			else				last->next = r;			last = r;			unlock(&listlock);			r->time = nsec();			if(write(fd, ip, msglen) < msglen){				fprint(2, "%s: write failed: %r\n", argv0);				return;			}			seq++;		}	}	done = 1;}voidrcvr(int fd, int msglen, int interval, int nmsg){	uchar buf[64*1024+512];	Icmp *ip;	ushort x;	int i, n, munged;	vlong now;	Req *r;	ip = (Icmp*)buf;	sum = 0;	while(lostmsgs+rcvdmsgs < nmsg){		alarm((nmsg-lostmsgs-rcvdmsgs)*interval+5000);		n = read(fd, buf, sizeof(buf));		alarm(0);		now = nsec();		if(n <= 0){	/* read interrupted - time to go */			clean(0, now+MINUTE, nil);			continue;		}		if(n < msglen){			print("bad len %d/%d\n", n, msglen);			continue;		}		munged = 0;		for(i = 32; i < msglen; i++)			if(buf[i] != (i&0xff))				munged++;		if(munged)			print("currupted reply\n");		x = nhgets(ip->seq);		if(ip->type != EchoReply || ip->code != 0) {			print("bad sequence/code/type %d/%d/%d\n",				ip->type, ip->code, x);			continue;		}		clean(x, now, ip);	}		lock(&listlock);	for(r = first; r; r = r->next)		if(r->replied == 0)			lostmsgs++;	unlock(&listlock);	if(lostmsgs)		print("%d out of %d messages lost\n", lostmsgs, lostmsgs+rcvdmsgs);}voidusage(void){	fprint(2, "usage: %s [-alq] [-s msgsize] [-i millisecs] [-n #pings] destination\n", argv0);	exits("usage");}voidmain(int argc, char **argv){	int fd;	int msglen, interval, nmsg;	nsec();		/* make sure time file is already open */	fmtinstall('V', eipfmt);	msglen = interval = 0;	nmsg = MAXMSG;	ARGBEGIN {	case 'l':		lostonly++;		break;	case 'd':		debug++;		break;	case 's':		msglen = atoi(ARGF());		break;	case 'i':		interval = atoi(ARGF());		break;	case 'n':		nmsg = atoi(ARGF());		break;	case 'a':		addresses = 1;		break;	case 'q':		quiet = 1;		break;	case 'r':		rint = 1;		break;	case 'f':		flood = 1;		break;	} ARGEND;	if(msglen < 32)		msglen = 64;	if(msglen >= 65*1024)		msglen = 65*1024-1;	if(interval <= 0 && !flood)		interval = SLEEPMS;	if(argc < 1)		usage();	notify(catch);	fd = dial(netmkaddr(argv[0], "icmp", "1"), 0, 0, 0);	if(fd < 0){		fprint(2, "%s: couldn't dial: %r\n", argv0);		exits("dialing");	}	print("sending %d %d byte messages %d ms apart\n", nmsg, msglen, interval);	switch(rfork(RFPROC|RFMEM|RFFDG)){	case -1:		fprint(2, "%s: can't fork: %r\n", argv0);	case 0:		rcvr(fd, msglen, interval, nmsg);		exits(0);	default:		sender(fd, msglen, interval, nmsg);		wait();		exits(lostmsgs ? "lost messages" : "");	}}voidreply(Req *r, Icmp *ip){	r->rtt /= 1000LL;	sum += r->rtt;	if(!r->replied)		rcvdmsgs++;	if(!quiet && !lostonly){		if(addresses)			print("%ud: %V->%V rtt %lld µs, avg rtt %lld µs, ttl = %d\n",				r->seq-firstseq,				ip->src, ip->dst,				r->rtt, sum/rcvdmsgs, r->ttl);		else			print("%ud: rtt %lld µs, avg rtt %lld µs, ttl = %d\n",				r->seq-firstseq,				r->rtt, sum/rcvdmsgs, r->ttl);	}	r->replied = 1;}voidlost(Req *r, Icmp *ip){	if(!quiet){		if(addresses)			print("lost %ud: %V->%V\n", r->seq-firstseq,				ip->src, ip->dst);		else			print("lost %ud\n", r->seq-firstseq);	}	lostmsgs++;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -