异步请求池的实现

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 异步请求池的实现

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

 

目录
相关文章
|
7月前
|
网络协议 NoSQL 关系型数据库
池式组件-异步请求池的原理与实现
池式组件-异步请求池的原理与实现
45 0
|
网络协议 NoSQL 关系型数据库
异步请求池
异步请求池
127 0
|
1月前
|
存储 JavaScript 中间件
在 Redux 动态路由中进行数据预加载时,如何处理数据加载失败的情况?
【10月更文挑战第22天】在 Redux 动态路由中进行数据预加载时,数据加载失败是需要妥善处理的情况
37 4
|
2月前
|
移动开发 前端开发 HTML5
SharedWorker 优化前端轮询请求
【10月更文挑战第6天】
42 1
|
7月前
使用代理IP池实现多线程的方法
使用代理IP池实现多线程的方法
|
7月前
|
网络协议 NoSQL 测试技术
异步请求池的实现
异步请求池的实现
62 0
|
7月前
|
域名解析 网络协议
异步请求池原理及实现
异步请求池原理及实现
|
7月前
|
安全 Java
C++11的半同步半异步线程池
C++11的半同步半异步线程池
68 0
|
7月前
|
JSON 前端开发 JavaScript
关于我认识的请求方式
关于我认识的请求方式有三个
72 0
|
网络协议 测试技术
异步请求池——池式组件
异步请求池——池式组件