网络编程|异步http客户端

【网络编程|异步http客户端】文章链接:https://codemouse.online/archives/2020-06-07180358
做法流程

1. init_context a.pthread_create b.epoll_create 2.uninit_context() a.pthread_cannel b.close 3.commit() a.准备socket b.connect c.protocol; dns/http/redis/mysql d.send e.epoll_ctl(add,sockfd); 4.callback() a.epoll_wait(); b.recv()

异步客户端
#include #include #include #include #include #include #include #include #include #include #include #include #include /* close */ #include #include #include #define HTTP_VERSION"HTTP/1.1" #define USER_AGENT"User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2\r\n" #define ENCODE_TYPE"Accept: text/html,application/xhtml+xml,application/xml; q=0.9,*/*; q=0.8\r\n" #define CONNECTION_TYPE "Connection: close\r\n" #define BUFFER_SIZE4096 #define ASYNC_CLIENT_NUM1024 #define HOSTNAME_LENGTH128 typedef void (*async_result_cb)(const char *hostname, const char *result); struct ep_arg { int sockfd; char hostname[HOSTNAME_LENGTH]; async_result_cb cb; }; struct async_context { int epfd; pthread_t thread_id; }; struct http_request { char *hostname; char *resource; }; int http_async_client_commit(struct async_context *ctx, const char *hostname, const char *resource, async_result_cb cb) {char *ip = host_to_ip(hostname); if (ip == NULL) return -1; int sockfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in sin = {0}; sin.sin_addr.s_addr = inet_addr(ip); sin.sin_port = htons(80); sin.sin_family = AF_INET; if (-1 == connect(sockfd, (struct sockaddr*)&sin, sizeof(struct sockaddr_in))) { return -1; } fcntl(sockfd, F_SETFL, O_NONBLOCK); char buffer[BUFFER_SIZE] = {0}; int len = sprintf(buffer, "GET %s %s\r\n\ Host: %s\r\n\ %s\r\n\ \r\n", resource, HTTP_VERSION, hostname, CONNECTION_TYPE ); printf("request buffer:%s\n", buffer); int slen = send(sockfd, buffer, strlen(buffer), 0); 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; int ret = epoll_ctl(ctx->epfd, EPOLL_CTL_ADD, sockfd, &ev); return ret; } static void *http_async_client_callback(void *arg) { struct async_context *ctx = (struct async_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 = https://www.it610.com/article/(struct ep_arg*)events[i].data.ptr; int sockfd = data->sockfd; char buffer[BUFFER_SIZE] = {0}; struct sockaddr_in addr; size_t addr_len = sizeof(struct sockaddr_in); int n = recv(sockfd, buffer, BUFFER_SIZE, 0); data->cb(data->hostname, buffer); //call cbint ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL); //printf("epoll_ctl DEL --> sockfd:%d\n", sockfd); close(sockfd); / free(data); }} } struct async_context *http_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) { close(epfd); return NULL; } ctx->epfd = epfd; int ret = pthread_create(&ctx->thread_id, NULL, http_async_client_callback, ctx); if (ret) { perror("pthread_create"); return NULL; } usleep(1); return ctx; } int http_async_client_uninit(struct async_context *ctx) { close(ctx->epfd); pthread_cancel(ctx->thread_id); return 0; } struct http_request reqs[] = { {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=beijing&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=changsha&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=shenzhen&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=shanghai&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=tianjin&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=wuhan&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=hefei&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=hangzhou&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=nanjing&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=jinan&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=taiyuan&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=wuxi&language=zh-Hans&unit=c" }, {"api.seniverse.com", "/v3/weather/now.json?key=0pyd8z7jouficcil&location=suzhou&language=zh-Hans&unit=c" }, }; static void http_async_client_result_callback(const char *hostname, const char *result) {printf("hostname:%s, result:%s\n\n\n\n", hostname, result); } int main(int argc, char *argv[]) { struct async_context *ctx = http_async_client_init(); if (ctx == NULL) return -1; int count = sizeof(reqs) / sizeof(reqs[0]); int i = 0; for (i = 0; i < count; i ++) { http_async_client_commit(ctx, reqs[i].hostname, reqs[i].resource, http_async_client_result_callback); } getchar(); }

    推荐阅读