1. 同步與異步的區別?
阻塞非阻塞
2. 如何設計?
思想: 客戶端發送n多請求給服務器,然後客戶端自己起一個線程,去輪詢服務器發送回來的應答,好像這個客戶端的線程起了一個服務一樣,等待服務器的應答消息,客戶端使用了epoll來管理這些IO。
3.部分代碼 -- 使用epoll來管理IO
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;
}
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 = (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 cb
int ret = epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, NULL);
//printf("epoll_ctl DEL --> sockfd:%d\n", sockfd);
close(sockfd); /////
free(data);
}
}
}