异步请求池的实现

 

1.一个连接还是多个连接?          多个

2.网络IO的基础,发送对应的协议。

3.既然是多个连接,发送完请求后,响应没有接收以前,fd存储在哪里?     

              fd由epoll进行管理,只关心可读事件,说明数据库返回了。

4. 请求与响应的数据不能做到一个线程。

如何设计



typedef void (*async_result_cb)(struct dns_item *arg, int count);

struct async_context {
	int epfd;
	pthread_t threadid;
};

struct ep_arg {
	int sockfd;
	async_result_cb cb;
};

#define ASYNC_EVENTS		128
void *dns_async_callback(void *arg) {

	struct async_context* ctx = (struct async_context*)arg;

	while (1) {
		struct epoll_event events[ASYNC_EVENTS] = {0};
		
		int nready = epoll_wait(ctx->epfd, events, ASYNC_EVENTS, -1);
		if (nready < 0) {
			continue;
		}

		int i = 0;
		for (i = 0;i < nready;i ++) {

			struct ep_arg *ptr = events[i].data.ptr;
			int sockfd = ptr->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);
				
			printf("recvfrom n : %d\n", n);
			struct dns_item *domains = NULL;
			int count = dns_parse_response(buffer, &domains);

			ptr->cb(domains, count);

			// sockfd 
			close (sockfd);

			free(ptr);
			// epollout --> 
			
			//epoll_ctl(ctx->epfd, EPOLL_CTL_MOD, sockfd, NULL);	
		}
	}
}

// 1 . context 
// 2 . return context;
// 
struct async_context* dns_async_client_init(void) {

	int epfd = epoll_create(1);
	if (epfd < 0) return NULL;

	struct async_context* ctx = calloc(1, sizeof(struct async_context));
	if (ctx == NULL) return NULL;

	ctx->epfd = epfd;

	int ret = pthread_create(&ctx->threadid, NULL, dns_async_callback, ctx);
	if (ret) {
		close(epfd);
		free(ctx);
		return NULL;
	}

	return ctx;
}


int dns_async_client_destroy(struct async_context* ctx) {

	close(ctx->epfd);
	pthread_cancel(ctx->threadid);
	

} 

int dns_async_client_commit(struct async_context *ctx, 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);

	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));

	struct ep_arg *ptr = calloc(1, sizeof(struct ep_arg));
	if (ptr == NULL) return -1;
	ptr->sockfd = sockfd;
	ptr->cb = cb;
	
	//
	struct epoll_event ev;
	ev.data.ptr = ptr;
	ev.events = EPOLLIN;
	epoll_ctl(ctx->epfd, EPOLL_CTL_ADD, sockfd, &ev);

	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值