亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? ping.c

?? socket編程的一個例子
?? C
?? 第 1 頁 / 共 2 頁
字號:
(1)主體代碼
ping代碼的主體部分可以四部分,首先是一些頭函數及宏定義: 
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/signal.h>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <resolv.h>
#define	F_FLOOD	0x001
#define	F_INTERVAL	0x002
#define	F_NUMERIC	0x004
#define	F_PINGFILLED	0x008
#define	F_QUIET	0x010
#define	F_RROUTE	0x020
#define	F_SO_DEBUG	0x040
#define	F_SO_DONTROUTE	0x080
#define	F_VERBOSE	0x100

/* 多播選項 */
int moptions;
#define MULTICAST_NOLOOP	0x001
#define MULTICAST_TTL		0x002
#define MULTICAST_IF		0x004
接下來的第二部分是建立socket并處理選項:
Int main(int argc, char *argv[])
{
	struct timeval timeout;
	struct hostent *hp;
	struct sockaddr_in *to;
	struct protoent *proto;
	struct in_addr ifaddr;
	int i;
	int ch, fdmask, hold, packlen, preload;
	u_char *datap, *packet;
	char *target, hnamebuf[MAXHOSTNAMELEN];
	u_char ttl, loop;
	int am_i_root;
	static char *null = NULL;

	/*__environ = &null;*/
	am_i_root = (getuid()==0);

	/*
	 *建立socket連接,并且測試是否是root用戶
	 */
	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
		if (errno==EPERM) {
			fprintf(stderr, "ping: ping must run as root\n");
		}
		else perror("ping: socket");
		exit(2);
	}
	preload = 0;
	datap = &outpack[8 + sizeof(struct timeval)];
	while ((ch = getopt(argc, argv, "I:LRc:dfh:i:l:np:qrs:t:v")) != EOF)
		switch(ch) {
		case 'c':
			npackets = atoi(optarg);
			if (npackets <= 0) {
				(void)fprintf(stderr,
				    "ping: bad number of packets to transmit.\n");
				exit(2);
			}
			break;
/*調用選項*/
		case 'd':
			options |= F_SO_DEBUG;
			break;
/*flood選項*/
		case 'f':
			if (!am_i_root) {
				(void)fprintf(stderr,
				    "ping: %s\n", strerror(EPERM));
				exit(2);
			}
			options |= F_FLOOD;
			setbuf(stdout, NULL);
			break;
/*等待選項*/
		case 'i':		/* wait between sending packets */
			interval = atoi(optarg);
			if (interval <= 0) {
				(void)fprintf(stderr,
				    "ping: bad timing interval.\n");
				exit(2);
			}
			options |= F_INTERVAL;
			break;
		case 'l':
			if (!am_i_root) {
				(void)fprintf(stderr,
				    "ping: %s\n", strerror(EPERM));
				exit(2);
			}
			preload = atoi(optarg);
			if (preload < 0) {
				(void)fprintf(stderr,
				    "ping: bad preload value.\n");
				exit(2);
			}
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;
	
	if (argc != 1)
		usage();
	target = *argv;

接下來的第三部分是用于獲取地址,這里主要使用了inet_aton函數,將點分十進制地址轉化為二進制地址。當然,作為完整的ping程序有較完善的出錯處理:
	memset(&whereto, 0, sizeof(struct sockaddr));
	to = (struct sockaddr_in *)&whereto;
	to->sin_family = AF_INET;
/*地址轉換函數*/
	if (inet_aton(target, &to->sin_addr)) {
		hostname = target;
	}
	else {
#if 0
		char * addr = resolve_name(target, 0);
		if (!addr) {
			(void)fprintf(stderr,
			    "ping: unknown host %s\n", target);
			exit(2);
		}
		to->sin_addr.s_addr = inet_addr(addr);
		hostname = target;
#else
/*調用gethostbyname識別主機名*/
		hp = gethostbyname(target);
		if (!hp) {
			(void)fprintf(stderr,
			    "ping: unknown host %s\n", target);
			exit(2);
		}
		to->sin_family = hp->h_addrtype;
		if (hp->h_length > (int)sizeof(to->sin_addr)) {
			hp->h_length = sizeof(to->sin_addr);
		}
		memcpy(&to->sin_addr, hp->h_addr, hp->h_length);
		(void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
		hostname = hnamebuf;
#endif
	}
接下來的一部分主要是對各個選項(如路由、多播)選項的處理,這里就不做介紹。再接下來是ping函數的最主要部分,就是接收無限循環接收回應信息,這里主要用到了函數recvfrom。另外,對用戶中斷信息也有相應的處理,如下所示:
	if (to->sin_family == AF_INET)
		(void)printf("PING %s (%s): %d data bytes\n", hostname,
		    inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr),
		    datalen);
	else
		(void)printf("PING %s: %d data bytes\n", hostname, datalen);
/*若程序接收到SIGINT或SIGALRM信號,調用相關的函數*/
	(void)signal(SIGINT, finish);
	(void)signal(SIGALRM, catcher);
/*循環等待客戶端的回應信息*/
	for (;;) {
		struct sockaddr_in from;
		register int cc;
		int fromlen;

		if (options & F_FLOOD) {
/*形成ICMP回應數據包,在后面會有講解*/
			pinger();
/*設定等待實踐*/
			timeout.tv_sec = 0;
			timeout.tv_usec = 10000;
			fdmask = 1 << s;
/*調用select函數*/
			if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL,
			    (fd_set *)NULL, &timeout) < 1)
				continue;
		}
		fromlen = sizeof(from);
/*接收客戶端信息*/
		if ((cc = recvfrom(s, (char *)packet, packlen, 0,
		    (struct sockaddr *)&from, &fromlen)) < 0) {
			if (errno == EINTR)
				continue;
			perror("ping: recvfrom");
			continue;
		}
		pr_pack((char *)packet, cc, &from);
		if (npackets && nreceived >= npackets)
			break;
	}
	finish(0);
	/* NOTREACHED */
	return 0;
}
(2)其他函數
下面的函數也是ping程序中用到的重要函數。首先catcher函數是用戶在發送SIGINT時調用的函數,在該函數中又調用了SIGALARM信號的處理來結束程序。
static void
catcher(int ignore)
{
	int waittime;

	(void)ignore;
	pinger();
/*調用catcher函數*/
	(void)signal(SIGALRM, catcher);
	if (!npackets || ntransmitted < npackets)
		alarm((u_int)interval);
	else {
		if (nreceived) {
			waittime = 2 * tmax / 1000;
			if (!waittime)
				waittime = 1;
			if (waittime > MAXWAIT)
				waittime = MAXWAIT;
		} else
			waittime = MAXWAIT;
/*調用finish函數,并設定一定的等待實踐*/
		(void)signal(SIGALRM, finish);
		(void)alarm((u_int)waittime);
	}
}
Pinger函數也是一個非常重要的函數,用于形成ICMP回應數據包,其中ID是該進程的ID,數據段中的前8字節用于存放時間間隔,從而可以計算ping程序從對端返回的往返時延差,這里的數據校驗用到了后面定義的in_cksum函數。其代碼如下所示:
static void
pinger(void)
{
	register struct icmphdr *icp;
	register int cc;
	int i;

/*形成icmp信息包,填寫icmphdr結構體中的各項數據*/
	icp = (struct icmphdr *)outpack;
	icp->icmp_type = ICMP_ECHO;
	icp->icmp_code = 0;
	icp->icmp_cksum = 0;
	icp->icmp_seq = ntransmitted++;
	icp->icmp_id = ident;			/* ID */

	CLR(icp->icmp_seq % mx_dup_ck);

/*設定等待實踐*/
	if (timing)
		(void)gettimeofday((struct timeval *)&outpack[8],
		    (struct timezone *)NULL);

	cc = datalen + 8;			/* skips ICMP portion */

	/* compute ICMP checksum here */
	icp->icmp_cksum = in_cksum((u_short *)icp, cc);

	i = sendto(s, (char *)outpack, cc, 0, &whereto,
	    sizeof(struct sockaddr));

	if (i < 0 || i != cc)  {
		if (i < 0)
			perror("ping: sendto");
		(void)printf("ping: wrote %s %d chars, ret=%d\n",
		    hostname, cc, i);
	}
	if (!(options & F_QUIET) && options & F_FLOOD)
		(void)write(STDOUT_FILENO, &DOT, 1);
}
pr_pack是數據包顯示函數,分別打印出IP數據包部分和ICMP回應信息。在規范的程序中通常將數據的顯示部分獨立出來,這樣可以很好地加強程序的邏輯性和結構性。
void
pr_pack(char *buf, int cc, struct sockaddr_in *from)
{
	register struct icmphdr *icp;
	register int i;
	register u_char *cp,*dp;
/*#if 0*/
	register u_long l;
	register int j;
	static int old_rrlen;
	static char old_rr[MAX_IPOPTLEN];
/*#endif*/
	struct iphdr *ip;
	struct timeval tv, *tp;
	long triptime = 0;
	int hlen, dupflag;

	(void)gettimeofday(&tv, (struct timezone *)NULL);

	/* 檢查IP數據包頭信息 */
	ip = (struct iphdr *)buf;
	hlen = ip->ip_hl << 2;
	if (cc < datalen + ICMP_MINLEN) {
		if (options & F_VERBOSE)
			(void)fprintf(stderr,
			  "ping: packet too short (%d bytes) from %s\n", cc,
			  inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
		return;
	}

	/* ICMP部分顯示 */
	cc -= hlen;
	icp = (struct icmphdr *)(buf + hlen);
	if (icp->icmp_type == ICMP_ECHOREPLY) {
		if (icp->icmp_id != ident)
			return;			/* 'Twas not our ECHO */
		++nreceived;
		if (timing) {
#ifndef icmp_data
			tp = (struct timeval *)(icp + 1);
#else
			tp = (struct timeval *)icp->icmp_data;
#endif
			tvsub(&tv, tp);
			triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100);
			tsum += triptime;
			if (triptime < tmin)
				tmin = triptime;
			if (triptime > tmax)
				tmax = triptime;
		}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产传媒一区在线| 在线中文字幕一区| 国产一区二区在线影院| 日本vs亚洲vs韩国一区三区| 亚洲成人你懂的| 亚洲成a人片综合在线| 亚洲成人在线免费| 石原莉奈在线亚洲三区| 丝袜亚洲精品中文字幕一区| 亚洲一卡二卡三卡四卡无卡久久| 伊人性伊人情综合网| 亚洲综合在线视频| 婷婷中文字幕一区三区| 视频一区在线视频| 日本中文字幕一区二区有限公司| 人人狠狠综合久久亚洲| 麻豆精品一二三| 国产又黄又大久久| 成人免费看黄yyy456| 99麻豆久久久国产精品免费 | 国产久卡久卡久卡久卡视频精品| 国产欧美日韩另类视频免费观看| 色狠狠桃花综合| 国产精品嫩草影院com| 国产精品美女一区二区三区| 中文字幕佐山爱一区二区免费| 亚洲精品国产第一综合99久久 | 91精品国产aⅴ一区二区| 日韩亚洲欧美高清| 中文字幕免费不卡| 一区二区欧美视频| 日韩综合在线视频| 懂色av一区二区三区蜜臀| 91色.com| 欧美不卡一区二区| 国产精品国产自产拍高清av王其| 一区二区三区在线观看视频 | 欧美日韩视频一区二区| 欧美一级二级三级乱码| 久久久精品欧美丰满| 亚洲欧美日韩一区二区三区在线观看| 中文字幕制服丝袜成人av | 精品成人私密视频| 精品国精品国产| 欧美激情在线一区二区| 亚洲视频资源在线| 亚洲视频每日更新| 日韩成人免费电影| 免费精品99久久国产综合精品| 大陆成人av片| 91久久奴性调教| 久久一夜天堂av一区二区三区| 亚洲国产精品成人综合色在线婷婷| 亚洲欧美另类小说视频| 亚洲成人激情综合网| 国产精品主播直播| 97se亚洲国产综合在线| 欧美成人一区二区三区片免费| 久久蜜桃av一区二区天堂| 亚洲自拍与偷拍| 老司机免费视频一区二区三区| 一本色道a无线码一区v| 91精品国产色综合久久ai换脸 | 日韩精品一区二区三区蜜臀| 日本黄色一区二区| 欧美日韩小视频| 国产精品女主播av| 香蕉久久一区二区不卡无毒影院 | 久久国产精品99精品国产| 成人97人人超碰人人99| 一本久久综合亚洲鲁鲁五月天| 精品国产人成亚洲区| 亚洲人成人一区二区在线观看 | 国产福利一区二区| 欧美日韩国产综合一区二区三区| 久久久蜜桃精品| 亚洲蜜桃精久久久久久久| 久久er精品视频| 欧美三片在线视频观看| 综合久久国产九一剧情麻豆| 美女视频一区在线观看| 欧美久久久一区| 国产精品二区一区二区aⅴ污介绍| 激情五月激情综合网| 欧美在线观看视频一区二区三区| 欧美激情一区在线观看| 免费一区二区视频| 国产精品久线在线观看| 在线播放亚洲一区| 欧美一区二区在线免费播放| 国产欧美日韩中文久久| 日韩不卡一二三区| 91久久久免费一区二区| 欧美韩日一区二区三区| 国产专区欧美精品| 欧美一区二区大片| 1区2区3区欧美| 国产精品18久久久久久久久| 精品国产一区二区三区久久久蜜月| 亚洲伊人色欲综合网| 成人爱爱电影网址| 国产日韩精品一区二区三区| 一区二区三区视频在线看| 蜜桃一区二区三区在线观看| 91福利小视频| 亚洲四区在线观看| www.欧美.com| 欧美国产1区2区| 国产盗摄女厕一区二区三区| 成人app下载| 亚洲免费在线播放| 99精品久久免费看蜜臀剧情介绍 | 国产欧美日韩在线观看| 久久国产精品无码网站| 5858s免费视频成人| 88在线观看91蜜桃国自产| 一级日本不卡的影视| 一区二区三区日韩在线观看| 亚洲最新在线观看| 国产91精品入口| 久久久久国产精品免费免费搜索 | 国产在线不卡一卡二卡三卡四卡| 日韩三级中文字幕| 青娱乐精品在线视频| 91精品办公室少妇高潮对白| 亚洲精品视频一区| 色婷婷激情一区二区三区| 国产精品免费丝袜| av不卡免费在线观看| 国产精品免费观看视频| 岛国精品在线观看| 久久久久九九视频| 懂色av噜噜一区二区三区av| 中文字幕av免费专区久久| 免费不卡在线视频| 日韩视频一区二区三区在线播放 | 欧美色涩在线第一页| 亚洲午夜精品网| 欧美一区二区三区在线看| 麻豆成人久久精品二区三区小说| 欧美日韩精品一区二区在线播放 | 欧美一区二区私人影院日本| 亚洲成人免费观看| 91精品国产综合久久久久久久| 日韩高清中文字幕一区| 欧美一级二级三级蜜桃| 国产在线国偷精品产拍免费yy| 欧美国产在线观看| 91视频免费看| 亚洲va韩国va欧美va精品| 91成人网在线| 久久99久久99精品免视看婷婷| 久久久精品蜜桃| 日本精品视频一区二区| 蜜臀a∨国产成人精品| 欧美日韩国产经典色站一区二区三区| 国产麻豆视频一区| 国产精品福利一区二区| 欧美丰满少妇xxxbbb| 韩国精品主播一区二区在线观看 | 国产精品女上位| 欧美怡红院视频| 麻豆免费看一区二区三区| 中文字幕高清不卡| 欧美日韩高清在线播放| 国产一区二区三区免费看| 亚洲激情六月丁香| 日韩一级片网站| 国产毛片精品视频| 亚洲一区二区三区四区不卡| 日韩视频在线观看一区二区| 成人激情小说乱人伦| 午夜免费久久看| 日韩精品一区二区三区视频在线观看| a级精品国产片在线观看| 丝袜美腿亚洲综合| 中文字幕一区二| 欧美一区二区女人| 97精品国产97久久久久久久久久久久 | 91免费看`日韩一区二区| 日韩精品电影在线| 国产精品国模大尺度视频| 欧美一区二区福利视频| 国产91精品免费| 一区二区三区免费网站| 久久夜色精品国产噜噜av| 成人免费视频国产在线观看| 日本亚洲视频在线| 亚洲精品视频在线观看免费| 欧美精品一区二区在线播放| 欧美性生活久久| 国产激情一区二区三区四区| 亚洲国产一区二区三区青草影视| 国产欧美一区二区精品忘忧草 | 国产a精品视频| 午夜精品久久一牛影视| 国产精品日韩成人| 久久久亚洲午夜电影| 91蝌蚪porny成人天涯| 成人的网站免费观看|