<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      異步請求池的實現(xiàn)

      今天分享一個異步請求池的例子。
      首先我們先看一個正常的阻塞的DNS解析的例子。

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      
      #include <errno.h>
      #include <fcntl.h>
      
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <netinet/in.h>
      
      #include <sys/epoll.h>
      #include <netdb.h>
      #include <arpa/inet.h>
      
      #include <pthread.h>
      
      
      #define DNS_SVR				"114.114.114.114"
      
      
      #define DNS_HOST			0x01
      #define DNS_CNAME			0x05
      
      
      
      struct dns_header {
      	unsigned short id;
      	unsigned short flags;
      	unsigned short qdcount;
      	unsigned short ancount;
      	unsigned short nscount;
      	unsigned short arcount;
      };
      
      struct dns_question {
      	int length;
      	unsigned short qtype;
      	unsigned short qclass;
      	char *qname;
      };
      
      struct dns_item {
      	char *domain;
      	char *ip;
      };
      
      int dns_create_header(struct dns_header *header) {
      
      	if (header == NULL) return -1;
      	memset(header, 0, sizeof(struct dns_header));
      
      	srandom(time(NULL));
      
      	header->id = random();
      	header->flags |= htons(0x0100);
      	header->qdcount = htons(1);
      
      	return 0;
      }
      
      int dns_create_question(struct dns_question *question, const char *hostname) {
      
      	if (question == NULL) return -1;
      	memset(question, 0, sizeof(struct dns_question));
      
      	question->qname = (char*)malloc(strlen(hostname) + 2);
      	if (question->qname == NULL) return -2;
      
      	question->length = strlen(hostname) + 2;
      
      	question->qtype = htons(1);
      	question->qclass = htons(1);
      
      	const char delim[2] = ".";
      
      	char *hostname_dup = strdup(hostname);
      	char *token = strtok(hostname_dup, delim);
      
      	char *qname_p = question->qname;
      
      	while (token != NULL) {
      
      		size_t len = strlen(token);
      
      		*qname_p = len;
      		qname_p ++;
      
      		strncpy(qname_p, token, len+1);
      		qname_p += len;
      
      		token = strtok(NULL, delim);
      	}
      
      	free(hostname_dup);
      
      	return 0;
      	
      }
      
      int dns_build_request(struct dns_header *header, struct dns_question *question, char *request) {
      
      	int header_s = sizeof(struct dns_header);
      	int question_s = question->length + sizeof(question->qtype) + sizeof(question->qclass);
      
      	int length = question_s + header_s;
      
      	int offset = 0;
      	memcpy(request+offset, header, sizeof(struct dns_header));
      	offset += sizeof(struct dns_header);
      
      	memcpy(request+offset, question->qname, question->length);
      	offset += question->length;
      
      	memcpy(request+offset, &question->qtype, sizeof(question->qtype));
      	offset += sizeof(question->qtype);
      
      	memcpy(request+offset, &question->qclass, sizeof(question->qclass));
      
      	return length;
      	
      }
      
      static int is_pointer(int in) {
      	return ((in & 0xC0) == 0xC0);
      }
      
      
      static void dns_parse_name(unsigned char *chunk, unsigned char *ptr, char *out, int *len) {
      
      	int flag = 0, n = 0, alen = 0;
      	char *pos = out + (*len);
      
      	while (1) {
      
      		flag = (int)ptr[0];
      		if (flag == 0) break;
      
      		if (is_pointer(flag)) {
      			
      			n = (int)ptr[1];
      			ptr = chunk + n;
      			dns_parse_name(chunk, ptr, out, len);
      			break;
      			
      		} else {
      
      			ptr ++;
      			memcpy(pos, ptr, flag);
      			pos += flag;
      			ptr += flag;
      
      			*len += flag;
      			if ((int)ptr[0] != 0) {
      				memcpy(pos, ".", 1);
      				pos += 1;
      				(*len) += 1;
      			}
      		}
      	
      	}
      	
      }
      
      
      static int dns_parse_response(char *buffer, struct dns_item **domains) {
      
      	int i = 0;
      	unsigned char *ptr = buffer;
      
      	ptr += 4;
      	int querys = ntohs(*(unsigned short*)ptr);
      
      	ptr += 2;
      	int answers = ntohs(*(unsigned short*)ptr);
      
      	ptr += 6;
      	for (i = 0;i < querys;i ++) {
      		while (1) {
      			int flag = (int)ptr[0];
      			ptr += (flag + 1);
      
      			if (flag == 0) break;
      		}
      		ptr += 4;
      	}
      
      	char cname[128], aname[128], ip[20], netip[4];
      	int len, type, ttl, datalen;
      
      	int cnt = 0;
      	struct dns_item *list = (struct dns_item*)calloc(answers, sizeof(struct dns_item));
      	if (list == NULL) {
      		return -1;
      	}
      
      	for (i = 0;i < answers;i ++) {
      		
      		bzero(aname, sizeof(aname));
      		len = 0;
      
      		dns_parse_name(buffer, ptr, aname, &len);
      		ptr += 2;
      
      		type = htons(*(unsigned short*)ptr);
      		ptr += 4;
      
      		ttl = htons(*(unsigned short*)ptr);
      		ptr += 4;
      
      		datalen = ntohs(*(unsigned short*)ptr);
      		ptr += 2;
      
      		if (type == DNS_CNAME) {
      
      			bzero(cname, sizeof(cname));
      			len = 0;
      			dns_parse_name(buffer, ptr, cname, &len);
      			ptr += datalen;
      			
      		} else if (type == DNS_HOST) {
      
      			bzero(ip, sizeof(ip));
      
      			if (datalen == 4) {
      				memcpy(netip, ptr, datalen);
      				inet_ntop(AF_INET , netip , ip , sizeof(struct sockaddr));
      
      				printf("%s has address %s\n" , aname, ip);
      				printf("\tTime to live: %d minutes , %d seconds\n", ttl / 60, ttl % 60);
      
      				list[cnt].domain = (char *)calloc(strlen(aname) + 1, 1);
      				memcpy(list[cnt].domain, aname, strlen(aname));
      				
      				list[cnt].ip = (char *)calloc(strlen(ip) + 1, 1);
      				memcpy(list[cnt].ip, ip, strlen(ip));
      				
      				cnt ++;
      			}
      			
      			ptr += datalen;
      		}
      	}
      
      	*domains = list;
      	ptr += 2;
      
      	return cnt;
      	
      }
      
      
      int dns_client_commit(const char *domain) {
      
      	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      	if (sockfd < 0) {
      		perror("create socket failed\n");
      		exit(-1);
      	}
      
      	printf("url:%s\n", domain);
      
      	struct sockaddr_in dest;
      	bzero(&dest, sizeof(dest));
      	dest.sin_family = AF_INET;
      	dest.sin_port = htons(53);
      	dest.sin_addr.s_addr = inet_addr(DNS_SVR);
      	
      	int ret = connect(sockfd, (struct sockaddr*)&dest, sizeof(dest));
      	printf("connect :%d\n", ret);
      
      	struct dns_header header = {0};
      	dns_create_header(&header);
      
      	struct dns_question question = {0};
      	dns_create_question(&question, domain);
      
      	char request[1024] = {0};
      	int req_len = dns_build_request(&header, &question, request);
      	int slen = sendto(sockfd, request, req_len, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));
      
      	char buffer[1024] = {0};
      	struct sockaddr_in addr;
      	size_t addr_len = sizeof(struct sockaddr_in);
      		
      	int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
      		
      	printf("recvfrom n : %d\n", n);
      	struct dns_item *domains = NULL;
      	dns_parse_response(buffer, &domains);
      
      	return 0;
      }
      
      char *domain[] = {
      //	"www.ntytcp.com",
      //	"bojing.wang",
      	"www.baidu.com",
      	"tieba.baidu.com",
      	"news.baidu.com",
      	"zhidao.baidu.com",
      	"music.baidu.com",
      	"image.baidu.com",
      	"v.baidu.com",
      	"map.baidu.com",
      	"baijiahao.baidu.com",
      	"xueshu.baidu.com",
      	"cloud.baidu.com",
      	"www.163.com",
      	"open.163.com",
      	"auto.163.com",
      	"gov.163.com",
      	"money.163.com",
      	"sports.163.com",
      	"tech.163.com",
      	"edu.163.com",
      	"www.taobao.com",
      	"q.taobao.com",
      	"sf.taobao.com",
      	"yun.taobao.com",
      	"baoxian.taobao.com",
      	"www.tmall.com",
      	"suning.tmall.com",
      	"www.tencent.com",
      	"www.qq.com",
      	"www.ctrip.com",
      	"hotels.ctrip.com",
      	"hotels.ctrip.com",
      	"vacations.ctrip.com",
      	"flights.ctrip.com",
      	"trains.ctrip.com",
      	"bus.ctrip.com",
      	"car.ctrip.com",
      	"piao.ctrip.com",
      	"tuan.ctrip.com",
      	"you.ctrip.com",
      	"g.ctrip.com",
      	"lipin.ctrip.com",
      	"ct.ctrip.com"
      };
      
      
      
      int main(int argc, char *argv[]) {
      
      	int count = sizeof(domain) / sizeof(domain[0]);
      	int i = 0;
      
      	for (i = 0;i < count;i ++) {
      		dns_client_commit(domain[i]);
      	}
      
      	getchar();
      	
      }
      

      1.commit 提交我們的請求

      2.thread_callback 線程監(jiān)控我們的請求是否可讀

      3.init()初始化我們的線程以及引入epoll

      4.destory 回收我們的資源

      首先我們先書寫一下我們的初始化函數(shù),進行epoll的初始化和線程的創(chuàng)建。

      typedef struct _ASYNC_CONTEXT
      {
      	int epfd;
      }ASYNC_CONTEXT,*PASYNC_CONTEXT;
      static void* lwl_dns_async_client_proc(void *arg) {
      	return nullptr;
      }
      int lwl_dns_async_init(PASYNC_CONTEXT ctx)
      {
      	if (ctx==NULL)
      	{
      		return -1;
      	}
      	int epfd = epoll_create(1);
      	if (epfd<0)
      	{
      		return -2;
      	}
      	ctx->epfd = epfd;
      	//init thread 
      	pthread_t thread_id;
      	
      	int ret = pthread_create(&thread_id, NULL, lwl_dns_async_client_proc, ctx);
      	if (ret)
      	{
      		perror("pthread_create failed!\n");
      		return -3;
      	}
      	usleep(1);
      	return NULL;	
      	
      }
      

      暫時先不完成我們線程回調(diào)函數(shù)的填寫。

      進下來我們來完成對commit 函數(shù)的編寫,在這里進行socket的初始化,并請求添加到epoll中

      static void lwl_dns_async_client_result_callback(struct dns_item*list, int count)
      {
      	int i = 0;
      	for (i = 0; i < count; i++)
      	{
      		printf("name:%s ip:%s\n", list[i].domain, list[i].ip);
      	}
      }
      //設(shè)置阻塞模式
      static int set_block(int fd, int block)
      {
      	int flags = fcntl(fd, F_GETFL, 0);
      	if (flags<0)
      	{
      		return flags;
      	}
      	if (block)
      	{
      		flags &= ~O_NONBLOCK;		
      	}
      	else
      	{		
      		flags |= O_NONBLOCK;
      	}
      	if (fcntl(fd,F_SETFL,flags)<0)
      	{
      		return -1;
      	}
      	return 0;
      }
      int lwl_dns_async_client_commit(PASYNC_CONTEXT ctx, const char* domain, async_result_cb cb)
      {
      	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      	if (sockfd<0)
      	{
      		perror("Create socket failed!\n");
      		exit(1);
      	}
      	printf("url: %s \n", domain);
      	//設(shè)置為非阻塞
      	set_block(sockfd, 0);
      	
      	struct sockaddr_in dest;
      	bzero(&dest, sizeof(dest));
      	dest.sin_family = AF_INET;
      	dest.sin_port = htons(53);
      	dest.sin_addr.s_addr = inet_addr(DNS_SVR);
      	
      	int ret = connect(sockfd, (struct sockaddr *)&dest, sizeof(dest));
      	
      	struct dns_header header = {0};
      	dns_create_header(&header);
      	
      	struct dns_question question = {0};
      	dns_create_question(&question, domain);
      	
      	char request[1024] = {0};
      	int req_len = dns_build_request(&header, &question, request);
      	int slen = sendto(sockfd, request, req_len, 0, (struct sockaddr *)&dest, sizeof(struct sockaddr));
      	
      	
      	struct ep_arg *eparg = (struct ep_arg*)calloc(1, sizeof(struct ep_arg));
      	
      	if (eparg==NULL)
      	{
      		return -1;
      	}
      	eparg->sockfd = sockfd;
      	eparg->cb = cb;
      	
      	struct epoll_event ev;
      	ev.data.ptr = eparg;
      	ev.events = EPOLLIN;
      	
      	ret = epoll_ctl(ctx->epfd, EPOLL_CTL_ADD, sockfd, &ev);
      	
      	
      }
      

      現(xiàn)在來填充線程的回調(diào)函數(shù),順便再把清理的函數(shù)完成編寫

      void lwl_dns_async_client_free_domains(struct dns_item *list, int count) {
      	int i = 0;
      
      	for (i = 0;i < count;i++) {
      		free(list[i].domain);
      		free(list[i].ip);
      	}
      
      	free(list);
      }
      
      
      //dns_async_client_proc()
      //epoll_wait
      //result callback
      static void* lwl_dns_async_client_proc(void *arg) {
      	PASYNC_CONTEXT ctx = (PASYNC_CONTEXT)arg;
      
      	int epfd = ctx->epfd;
      
      	while (1) {
      
      		struct epoll_event events[ASYNC_CLIENT_NUM] = {0};
      
      		int nready = epoll_wait(epfd, events, ASYNC_CLIENT_NUM, -1);
      		if (nready < 0) {
      			if (errno == EINTR || errno == EAGAIN) {
      				continue;
      			}
      			else {
      				break;
      			}
      		}
      		else if (nready == 0) {
      			continue;
      		}
      
      		printf("nready:%d\n", nready);
      		int i = 0;
      		for (i = 0;i < nready;i++) {
      
      			struct ep_arg *data = (struct ep_arg*)events[i].data.ptr;
      			int sockfd = data->sockfd;
      
      			char buffer[1024] = {0};
      			struct sockaddr_in addr;
      			size_t addr_len = sizeof(struct sockaddr_in);
      			int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
      			struct dns_item *domain_list = NULL;
      			int count = dns_parse_response(buffer, &domain_list);
      
      			data->cb(domain_list, count); //call cb
      			
      			int ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
      			//printf("epoll_ctl DEL --> sockfd:%d\n", sockfd);
      
      			close(sockfd); /////
      
      			dns_async_client_free_domains(domain_list, count);
      			free(data);
      
      		}
      		
      	}
      	
      }
      
      

      按照我們所寫的4個步驟,我們就完成了代碼的編寫。這個異步連接池的思想,先初始化我們的EPOLL和線程,再去線程回調(diào)中進行EPOLL有信號的處理,添加任務(wù)則在主線程中進行添加,避免卡頓在我們的主線程中。

      posted @ 2023-02-15 18:28  飄雨的河  閱讀(36)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产亚洲精久久久久久无码77777| 人妻中出无码一区二区三区| 日韩精品福利一区二区三区| 成年男女免费视频网站| 免费日韩av网在线观看| 国内少妇人妻偷人精品| 欧洲精品色在线观看| 成人自拍小视频在线观看| 久久久天堂国产精品女人| 亚洲av无码之国产精品网址蜜芽 | 无码粉嫩虎白一线天在线观看| 欧美日韩在线亚洲二区综二| 大地资源免费视频观看| 融水| 97av| 鲁丝一区二区三区免费| 波密县| 在线观看精品视频网站| 国产精品国产三级国AV | 国产一区二区波多野结衣| 一区二区三区精品偷拍| 国产福利酱国产一区二区| 亚洲国产日韩精品久久| 伊人久久大香线蕉AV网禁呦| 国产午夜一区二区在线观看| 国产精品一起草在线观看| 人妻丝袜AV中文系列先锋影音| 免费吃奶摸下激烈视频| 国产无遮挡免费真人视频在线观看| 福利视频在线播放| 少妇午夜福利一区二区三区| 特级做a爰片毛片免费看无码| 国内久久人妻风流av免费| 青青青爽在线视频观看| 亚洲人成电影在线天堂色| 乱女乱妇熟女熟妇综合网| 久久人妻无码一区二区三区av| 欧美做受视频播放| 国产综合久久久久鬼色| 在线精品视频一区二区| 在线高清理伦片a|