Libevent is usually used as a server, but there are scenarios where it will be used as a client to fetch other services. Usually, libcurl can be used to fetch, but the entire thread will be in a waiting state. In this case, the libevent client mode can be used to make the request completely asynchronous. .
#ifndef _EVENT_CURL_H_ #define _EVENT_CURL_H_ #include <string> using namespace std; typedef void (*RequestFinishHandler)(struct evhttp_request *req, void *arg); struct event_base; class EventHttpReq { public: EventHttpReq() { m_time_out = 300; finish_handler = NULL; finish_arg = NULL; } string m_url; string m_post_data; int m_time_out; RequestFinishHandler finish_handler; void *finish_arg; }; class EventCurl { public: static bool curl(EventHttpReq &eventHttpReq, struct event_base *, struct evhttp_connection *& conn); }; #endif
#include <signal.h> #include <sys/socket.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <arpa/inet.h> #include <netinet/tcp.h> #include "EventCurl.h" #include "event2/util.h" #include "event2/http.h" #include "event2/http_struct.h" #include "event2/buffer.h" bool EventCurl::curl(EventHttpReq &eventHttpReq, struct event_base *base, struct evhttp_connection *& conn) { struct evhttp_request *req; const char *scheme, *host, *path, *query; struct evhttp_uri *http_uri = evhttp_uri_parse(eventHttpReq.m_url.c_str()); if (NULL == http_uri) { return false; } string uri; int port; scheme = evhttp_uri_get_scheme(http_uri); if (scheme == NULL || (strcasecmp(scheme, "https") != 0 && strcasecmp(scheme, "http") != 0)) { evhttp_uri_free(http_uri); return false; } host = evhttp_uri_get_host(http_uri); if (NULL == host) { evhttp_uri_free(http_uri); return false; } port = evhttp_uri_get_port(http_uri); if (port == -1) { port = (strcasecmp(scheme, "http") == 0) ? 80 : 443; } path = evhttp_uri_get_path(http_uri); if (path == NULL || strlen(path) == 0) { uri = "/"; } else { uri = path; } query = evhttp_uri_get_query(http_uri); if (query != NULL) { uri += "?"; uri += query; } conn = evhttp_connection_base_new(base, NULL, host, port); if (NULL == conn) { evhttp_uri_free(http_uri); return false; } req = evhttp_request_new(eventHttpReq.finish_handler, eventHttpReq.finish_arg); if (NULL == req) { evhttp_connection_free(conn); evhttp_uri_free(http_uri); conn = NULL; return false; } evhttp_add_header(req->output_headers, "Host", host); int make_request_ret = 0; if (eventHttpReq.m_post_data.size() > 0) //post request, add the content of post { evbuffer_add(req->output_buffer, eventHttpReq.m_post_data.c_str(), eventHttpReq.m_post_data.size()); make_request_ret = evhttp_make_request(conn, req, EVHTTP_REQ_POST, uri.c_str()); } else //get request { make_request_ret = evhttp_make_request(conn, req, EVHTTP_REQ_GET, uri.c_str()); } if (make_request_ret != 0) { evhttp_connection_free(conn); evhttp_request_free(req); evhttp_uri_free(http_uri); conn = NULL; return false; } evhttp_connection_set_timeout(req->evcon, eventHttpReq.m_time_out); evhttp_uri_free(http_uri); return true; }
Receive the return result, or handle exceptions.
void finish_handler(struct evhttp_request *req, void *arg) { EParser *parser = (EParser *)arg; parser->m_curl_time = parser->m_timer.ElapseTime(); int http_code = 0; if (req != NULL) { http_code = evhttp_request_get_response_code(req); //http码 parser->m_http_code = http_code; if (http_code == HTTP_OK) { int s = evbuffer_remove(req->input_buffer, &parser->curl_result, E_MAX_SIZE_BUF); struct evkeyvalq* headers = evhttp_request_get_input_headers(req); //http头部 for (evkeyval* header = headers->tqh_first; header != NULL; header = header->next.tqe_next) { parser->m_receive_header.insert(std::pair<string, string>(header->key, header->value)); } } } parser->m_is_finish = true; ProcessRequestSend(EParser); }