libevent作为客户端

         libevent通常作为服务端,但是有场景会作为客户端去抓取别的服务,通常可以使用libcurl去抓取,但是会使整个线程处于等待状态,这时可以使用libevent客户端模式,使请求完全异步。

    

#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请求,则加入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请求
    {
        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;
}

    收到返回结果,或异常时的处理。

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

猜你喜欢

转载自shaojiashuai123456.iteye.com/blog/2403714