网络编程|异步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();
}
推荐阅读
- 画解算法(1.|画解算法:1. 两数之和)
- ts泛型使用举例
- https请求被提早撤回
- HTTP高级(Cookie,Session|HTTP高级(Cookie,Session ,LocalStorage )
- 拒绝可以很艺术,或者很行为艺术。
- www和https://又被Chrome地址栏隐藏了
- Spring集成|Spring集成 Mina
- 零基础学习Python作业本(13)
- AnyProxy抓取http/https请求
- 网络编程基础--HTTP